TopTL 0.1.0

dotnet add package TopTL --version 0.1.0
                    
NuGet\Install-Package TopTL -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TopTL" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TopTL" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="TopTL" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TopTL --version 0.1.0
                    
#r "nuget: TopTL, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TopTL@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TopTL&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=TopTL&version=0.1.0
                    
Install as a Cake Tool

TOP.TL C# SDK

NuGet Downloads .NET License TOP.TL

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/profileAPI 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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