API
Post your server count, check whether a user has voted, and receive a webhook when they do.
Authentication
Generate a token from your bot's edit page. Send it in the Authorization header, with or without a Bearer prefix — both work, so code written against other bot lists needs no changes.
Authorization: dbl_your_token_hereA token belongs to one bot and can only act on that bot. Requests for a different bot answer 404. Rate limits are per token, not per IP, so a sharded bot is not throttled for having many addresses.
Endpoints
POST/api/v1/bots/{bot_id}/stats
Update your server count. Accepts server_count, serverCount or guildCount, so an existing integration works unchanged.
curl -X POST https://discordbotlist.lol/api/v1/bots/YOUR_BOT_ID/stats \
-H "Authorization: dbl_your_token_here" \
-H "Content-Type: application/json" \
-d '{"server_count": 1200}'60 requests per minute.
GET/api/v1/bots/{bot_id}/check?userId={user_id}
Whether a user has voted within the last 12 hours. This is the call to make when someone runs a perk-gated command.
{
"voted": 1,
"hasVoted": true,
"votedAt": "2026-09-02T10:15:00.000Z",
"nextVoteAt": "2026-09-02T22:15:00.000Z"
}nextVoteAt saves you reimplementing the cooldown. 600 requests per minute, because this one is called per command.
GET/api/v1/bots/{bot_id}/votes?limit=50
Recent votes, newest first. Returns user ids and timestamps only.
{
"votes": [
{ "user_id": "123456789012345678", "voted_at": "2026-09-02T10:15:00.000Z" }
]
}Maximum limit 100. 60 requests per minute.
PUT/api/v1/bots/{bot_id}/commands
Publish your command list. It appears on your bot's page and on its own /commands page, which is indexable and is where a search for “your bot commands” should land.
curl -X PUT https://discordbotlist.lol/api/v1/bots/YOUR_BOT_ID/commands \
-H "Authorization: YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"commands":[{"name":"ban","description":"Ban a member"}]}'Send it on startup, after you register your application commands with Discord. The field names match Discord's own command objects, so you can forward what you already built.
Replaces the whole list, so a command you drop disappears here too. At most 50 commands; names up to 32 characters, descriptions up to 100. 10 requests per minute.
GET/api/v1/bots/{bot_id}/widget
An SVG vote-count badge. No authentication — it is meant for a README, a project site or a support server, where no key could be kept secret anyway. It updates on its own.
Wrap it in a link to your bot's page. A bare image is a picture of a number; the link is what sends a reader who is already interested somewhere they can vote.
[](https://discordbotlist.lol/bot/YOUR_BOT_ID)Your bot's edit page has both snippets with the ids already filled in, plus an HTML version, ready to copy.
Vote webhook
Set a URL on your bot's edit page and we POST to it whenever someone votes. Failed deliveries retry five times over about two and a half hours, and the last ten attempts are listed on that page with their status codes.
POST https://your-bot.example.com/webhooks/votes
Authorization: <your webhook secret>
X-Webhook-Event: vote.create
X-Webhook-Signature-256: sha256=<hmac of the raw body>
{
"event": "vote.create",
"bot_id": "123456789012345678",
"user_id": "987654321098765432",
"voted_at": "2026-09-02T10:15:00.000Z"
}Verify either the Authorization header or the signature, and reject requests carrying neither. The signature is the safer of the two if your logs capture headers.
The URL must be https on a public host. Loopback and private addresses are refused.
Posting through BotBlock
The stats endpoint follows the field names every bot list uses (server_count, with a bare token in the Authorization header), so a library that already posts to several lists can add this one as configuration rather than as code.
// blapi
const blapi = require('blapi');
blapi.handle(client, {
'discordbotlist.lol': 'YOUR_API_TOKEN',
});Get the token from your bot's edit page. It is shown once; if you lose it, generate a new one, which invalidates the old.
Errors
400— the body or a query parameter is malformed.401— missing, malformed or unknown token.404— no such bot, or the token belongs to a different one.429— rate limited; the body carriesretryAfter.
Need a token? List your bot and generate one from its edit page.