TopTL 0.1.0
dotnet add package TopTL --version 0.1.0
NuGet\Install-Package TopTL -Version 0.1.0
<PackageReference Include="TopTL" Version="0.1.0" />
<PackageVersion Include="TopTL" Version="0.1.0" />
<PackageReference Include="TopTL" />
paket add TopTL --version 0.1.0
#r "nuget: TopTL, 0.1.0"
#:package TopTL@0.1.0
#addin nuget:?package=TopTL&version=0.1.0
#tool nuget:?package=TopTL&version=0.1.0
TOP.TL C# SDK
The official C# SDK for TOP.TL — post stats, check votes, and manage vote webhooks for your Telegram bot, channel, or group listed on top.tl.
Targets net8.0 (LTS) and net6.0. No third-party runtime dependencies — uses only System.Net.Http and System.Text.Json.
Install
dotnet add package TopTL
or via the NuGet Package Manager:
Install-Package TopTL
Quickstart
Get an API key at https://top.tl/profile → API Keys. Scope the key to your listing and the operations you need (listing:read, listing:write, votes:read, votes:check).
using TopTL;
using var client = new TopTLClient("toptl_xxx");
// Fetch a listing
var listing = await client.GetListingAsync("mybot");
Console.WriteLine($"{listing.Title} — {listing.VoteCount} votes");
// Post stats on a listing you own
await client.PostStatsAsync("mybot", new StatsPayload
{
MemberCount = 5_000,
GroupCount = 1_200,
ChannelCount = 300,
});
// Reward users who voted
var check = await client.HasVotedAsync("mybot", 123456789);
if (check.Voted)
GrantPremiumAccess(userId: 123456789);
Dependency injection / IHttpClientFactory
Share an HttpClient managed by the framework rather than creating a new one per client:
services.AddHttpClient<TopTLClient>();
// or
var http = httpClientFactory.CreateClient("toptl");
var client = new TopTLClient("toptl_xxx", http);
Autoposter
For long-running bot processes, the SDK ships with a background autoposter that calls PostStatsAsync on an interval and, when onlyOnChange: true, only hits the API when the counters actually changed:
using var client = new TopTLClient("toptl_xxx");
var poster = new Autoposter(
client,
"mybot",
async ct => new StatsPayload { MemberCount = await bot.GetMemberCountAsync(ct) },
interval: TimeSpan.FromMinutes(30),
onlyOnChange: true);
poster.OnPost += (_, stats) => Console.WriteLine($"Posted: {stats.MemberCount} members");
poster.OnError += (_, err) => Console.WriteLine($"Autopost failed: {err.Message}");
poster.Start();
// On shutdown:
await poster.StopAsync();
For cron-style one-shots, skip the autoposter and call client.PostStatsAsync(...) directly.
Vote webhooks
Register a URL TOP.TL will POST to whenever someone votes for your listing:
await client.SetWebhookAsync(
"mybot",
url: "https://mybot.example.com/toptl-vote",
rewardTitle: "30-day premium"); // shown to the voter
// Fire a synthetic test event to verify your endpoint
var result = await client.TestWebhookAsync("mybot");
Console.WriteLine($"{result.Success} — HTTP {result.StatusCode}");
The webhook payload contains the voting user (userId, firstName, username), the listing, and a timestamp.
Batch stats
Post stats for up to 25 listings in a single request:
var results = await client.BatchPostStatsAsync(new[]
{
new BatchStatsItem { Username = "bot1", MemberCount = 1_200 },
new BatchStatsItem { Username = "bot2", MemberCount = 5_400 },
});
Global stats
var stats = await client.GetGlobalStatsAsync();
Console.WriteLine($"{stats.Channels} channels, {stats.Groups} groups, {stats.Bots} bots");
Error handling
Every API error raises a subclass of TopTLException:
try
{
await client.PostStatsAsync("mybot", new StatsPayload { MemberCount = 5_000 });
}
catch (TopTLAuthenticationException) { /* bad key or missing scope */ }
catch (TopTLNotFoundException) { /* listing does not exist */ }
catch (TopTLRateLimitException) { /* back off and retry */ }
catch (TopTLValidationException ex) { /* inspect ex.ResponseBody */ }
catch (TopTLException ex) { /* transport / 5xx fallback */ }
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 93 | 4/21/2026 |