A .NET client library for the Top.gg API - manage Discord bot stats, votes, and more in your .NET applications.
dotnet add package TopGG- Full Top.gg API v0 and v1 support
- Fully async/await API
- Type-safe enums for sorting and Discord commands
- Fluent API for bot search queries
- Built-in dependency injection support
- Comprehensive error handling with RFC 7807 ProblemDetails
- Rate limit handling with retry information
- Supports .NET Standard 2.0+ (.NET Framework 4.6.2+, .NET Core 2.0+, .NET 5+)
- Cancellation token support
using TopGG.Client;
// Option 1: Direct instantiation
using var client = new TopGGClient("your-topgg-token", botId: 123456789012345678);
// Option 2: Using the builder pattern
var client = TopGGClientBuilder.Create()
.WithToken("your-topgg-token")
.WithBotId(123456789012345678)
.Build();
// Option 3: From environment variables (recommended for production)
var client = TopGGClientBuilder.Create()
.WithTokenFromEnvironment() // Reads TOPGG_TOKEN
.WithBotIdFromEnvironment() // Reads TOPGG_BOT_ID
.Build();
// Search for bots
var result = await client.SearchBotsAsync(limit: 5);
foreach (var bot in result.Results)
{
Console.WriteLine($"{bot.Username} has {bot.Points} votes!");
}
// Post your bot's guild count
await client.PostBotStatsAsync(guildCount: 1500);
// Check if a user has voted
var voteCheck = await client.CheckUserVoteAsync(987654321012345678);
Console.WriteLine($"User has voted: {voteCheck.HasVoted}");// Direct instantiation
using var client = new TopGGClient("your-topgg-token", botId: 123456789012345678);
// Or using builder
var client = TopGGClientBuilder.Create()
.WithToken("your-topgg-token")
.WithBotId(123456789012345678)
.Build();
// Search for bots
var bots = await client.SearchBotsAsync(limit: 10);
foreach (var bot in bots.Results)
{
Console.WriteLine($"Bot: {bot.Username}");
Console.WriteLine($"Servers: {bot.ServerCount}");
Console.WriteLine($"Votes: {bot.Points}");
}
// Get your bot's stats
var stats = await client.GetBotStatsAsync();
Console.WriteLine($"Server Count: {stats.ServerCount}");
// Post your bot's stats
await client.PostBotStatsAsync(guildCount: 1500);
// Get last 1000 voters
var votes = await client.GetBotVotesAsync();
foreach (var vote in votes.Take(5))
{
Console.WriteLine($"Voter: {vote.Username} ({vote.Id})");
}using TopGG.Enums;
// Search for bots with fluent API
var result = await client.Search()
.WithLimit(10)
.SortBy(BotSortField.PointsDesc) // Sort by votes descending
.ExecuteAsync();
foreach (var bot in result.Results)
{
Console.WriteLine($"{bot.Username}: {bot.Points} votes");
}// Get detailed vote status
var voteStatus = await client.GetVoteStatusAsync(987654321012345678);
Console.WriteLine($"Last voted: {voteStatus.CreatedAt}");
Console.WriteLine($"Can vote again: {voteStatus.ExpiresAt}");
Console.WriteLine($"Vote weight: {voteStatus.Weight}");using TopGG.Models.Discord;
using TopGG.Enums.Discord;
var commands = new[]
{
new ApplicationCommand
{
Name = "help",
Description = "Shows the help menu",
Type = ApplicationCommandType.ChatInput
},
new ApplicationCommand
{
Name = "ping",
Description = "Check bot latency",
Type = ApplicationCommandType.ChatInput,
Options = new List<ApplicationCommandOption>
{
new()
{
Name = "ephemeral",
Description = "Whether to show the response only to you",
Type = ApplicationCommandOptionType.Boolean,
Required = false
}
}
}
};
await client.UpdateBotCommandsAsync(commands);// In Program.cs or Startup.cs
services.AddTopGGClient("your-topgg-token", botId: 123456789012345678);
// In your service/controller
public class BotService
{
private readonly ITopGGClient _client;
public BotService(ITopGGClient client)
{
_client = client;
}
public async Task PostStatsAsync(int serverCount)
{
await _client.PostBotStatsAsync(serverCount);
}
public async Task<bool> HasUserVotedAsync(ulong userId)
{
var result = await _client.CheckUserVoteAsync(userId);
return result.HasVoted;
}
}services.AddTopGGClient("your-topgg-token", botId: 123456789012345678, httpClient =>
{
httpClient.Timeout = TimeSpan.FromSeconds(30);
});using TopGG.Exceptions;
try
{
var stats = await client.GetBotStatsAsync();
await client.PostBotStatsAsync(guildCount: 100);
}
catch (TopGGNotFoundException ex)
{
// Resource not found (404)
Console.WriteLine($"Not found: {ex.Message}");
}
catch (TopGGRateLimitException ex)
{
// Rate limited (429)
Console.WriteLine($"Rate limited! Retry after: {ex.RetryAfter}");
}
catch (TopGGBadRequestException ex)
{
// Client errors (400-level)
Console.WriteLine($"Bad request ({ex.StatusCode}): {ex.Message}");
}
catch (TopGGServerException ex)
{
// Server errors (500-level)
Console.WriteLine($"Server error ({ex.StatusCode}): {ex.Message}");
}
catch (TopGGException ex)
{
// Network errors, timeouts, etc.
Console.WriteLine($"Error: {ex.Message}");
}| Method | Returns | Description |
|---|---|---|
SearchBotsAsync(limit?, offset?, sort?, fields?, cancellationToken?) |
BotSearchResult |
Search for bots on Top.gg |
GetBotStatsAsync(cancellationToken?) |
BotStats |
Get your bot's statistics (requires bot ID in client) |
PostBotStatsAsync(guildCount, cancellationToken?) |
Task |
Post your bot's guild count |
GetBotVotesAsync(cancellationToken?) |
Vote[] |
Get last 1000 voters for your bot |
CheckUserVoteAsync(userId, cancellationToken?) |
VoteCheck |
Check if a user voted in last 12 hours |
| Method | Returns | Description |
|---|---|---|
UpdateBotCommandsAsync(commands, cancellationToken?) |
Task |
Update slash commands on Top.gg |
GetVoteStatusAsync(userId, source?, cancellationToken?) |
VoteStatus |
Get detailed vote status (timestamps, weight) |
The Search() method returns a BotSearchBuilder for constructing queries:
| Method | Description |
|---|---|
Search() |
Create a search builder |
.WithLimit(n) |
Set max results (max 500, default 50) |
.WithOffset(n) |
Skip n results (for pagination) |
.SortBy(field) |
Sort by field (use *Desc variants for descending) |
.WithFields(params string[]) |
Select specific fields to return |
.IncludeField(field) |
Add a single field to the selection |
.ExecuteAsync(cancellationToken?) |
Execute the search and return results |
Available sort fields for the SortBy() method:
Username/UsernameDesc- Sort by bot usernameId/IdDesc- Sort by bot IDServerCount/ServerCountDesc- Sort by server countPoints/PointsDesc- Sort by total votesMonthlyPoints/MonthlyPointsDesc- Sort by monthly votesDate/DateDesc- Sort by submission date
Bot - Returned from search results
public class Bot
{
public ulong Id { get; set; }
public string Username { get; set; }
public int Points { get; set; } // Total votes
public int MonthlyPoints { get; set; } // Monthly votes
public int? ServerCount { get; set; }
public string? Prefix { get; set; }
public string? ShortDescription { get; set; }
public List<string>? Tags { get; set; }
public string? Website { get; set; }
public string? Invite { get; set; }
// ... and more properties
}BotStats - Your bot's statistics
public class BotStats
{
public int? ServerCount { get; set; }
}Vote - A vote from GetBotVotesAsync()
public class Vote
{
public ulong Id { get; set; }
public string Username { get; set; }
public string? Avatar { get; set; }
}VoteCheck - Result from CheckUserVoteAsync()
public class VoteCheck
{
public int Voted { get; set; }
public bool HasVoted { get; } // Computed property (true if Voted == 1)
}VoteStatus - Detailed vote info from GetVoteStatusAsync()
public class VoteStatus
{
public DateTime CreatedAt { get; set; } // When user last voted
public DateTime ExpiresAt { get; set; } // When user can vote again
public int Weight { get; set; } // Vote multiplier
}The TopGGClientBuilder provides a fluent API for creating clients:
var client = TopGGClientBuilder.Create()
.WithToken("your-token")
.WithBotId(123456789012345678)
.Build();The builder supports loading configuration from environment variables:
// Uses default variable names: TOPGG_TOKEN and TOPGG_BOT_ID
var client = TopGGClientBuilder.Create()
.WithTokenFromEnvironment()
.WithBotIdFromEnvironment()
.Build();
// Or use custom environment variable names
var client = TopGGClientBuilder.Create()
.WithTokenFromEnvironment("MY_CUSTOM_TOKEN")
.WithBotIdFromEnvironment("MY_CUSTOM_BOT_ID")
.Build();Default environment variables:
| Variable | Description |
|---|---|
TOPGG_TOKEN |
Your Top.gg API token |
TOPGG_BOT_ID |
Your bot's Discord ID |
var builder = TopGGClientBuilder.Create()
.WithTokenFromEnvironment()
.WithBotIdFromEnvironment();
if (builder.TryBuild(out var client))
{
// Client created successfully
await client.PostBotStatsAsync(100);
}
else
{
Console.WriteLine("Failed to create client - check your configuration");
}
## License
MIT
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Credits
This library is a wrapper for the [Top.gg API](https://docs.top.gg).