Docs academy · Guide 8 of 8 · 12 min read

Listing on Nexobots and posting stats

Submit your bot, pass review, post your server count and react to votes over the API.


Before you submit

Reviewers test your bot by hand. Save yourself a denial by checking these first:

  • Your bot is online and responds to its commands.
  • It doesn't collect tokens or IP addresses, and it isn't a copy of another bot.
  • Your description matches what it actually does.
  • NSFW is flagged if your bot has adult content.
  • It asks only for the permissions it needs. See guide 4. Administrator is only allowed as an exception: you have to explain why, only our review team sees your reason, and a Moderator or Administrator decides. Most bots are better off without it.

Add your bot

Go to Add a listing and choose Bot. It takes about five minutes.

  1. Paste your client ID. We fetch your bot's name, avatar and description from Discord, so you don't have to type them.
  2. Prove you own it. We show a one-time code that looks like nexo-verify-7F3KQ2. Paste it into your application's Description on the General Information page of the Developer Portal and save, then click verify. Discord can take a minute to update. Once you're verified, you can remove the code.
  3. Fill in your listing. That's a short description (up to 140 characters), a long description in Markdown, up to 5 tags, your prefix or slash commands, and the permissions for your invite link. Add your support server, website, GitHub and your bot's privacy policy if you have them.
  4. Submit. Automatic checks run first, then a person reviews your bot. We aim to finish within 48 hours, and your dashboard shows a live estimate.

If your bot is denied, you'll get the reason and usually a note from the reviewer, by Discord DM and email. Most denials can be fixed and resubmitted from your dashboard.

You can add team members once your bot is approved.

Add your commands

Your listing has a Commands section, which shows on your bot's page and tells reviewers what to try. Type them in, or import a .json file:

[
  { "name": "play", "description": "Play a song", "usage": "/play <song>" },
  { "name": "skip", "description": "Skip the current song" }
]

You can also import what Discord's API returns for your application's commands. We work out the usage from the options, and leave out right-click menu commands.

Get your API token

Open your bot in the dashboard and generate an API token. We show it only once, and we store only a hash of it. If you lose it, generate a new one, which invalidates the old one.

Treat it like your Discord token: keep it in your .env file.

NEXOBOTS_TOKEN=nexo_your_token_here

Post your server count

Send your count to POST /v1/bots/:id/stats, where :id is your bot's client ID. You can post once every 5 minutes. Posting every 30 minutes is plenty, and it also tells us your bot is alive.

We have official SDKs for both languages, and they handle the requests for you. Install the one you need:

npm install @nexobots/sdk   # discord.js
pip install nexobots        # discord.py

With discord.js:

import { Nexobots } from "@nexobots/sdk";

client.once(Events.ClientReady, (ready) => {
  const nexobots = new Nexobots({ token: process.env.NEXOBOTS_TOKEN, botId: ready.user.id });

  // Posts now and every 30 minutes.
  nexobots.autopost(() => ({ serverCount: ready.guilds.cache.size }), { onError: console.error });
});

If you're sharded, get your total with fetchClientValues as shown in guide 7, and post from one shard only.

With discord.py, using the tasks extension:

import os

from discord.ext import tasks
from nexobots import Nexobots


@tasks.loop(minutes=30)
async def post_stats():
    async with Nexobots(os.environ["NEXOBOTS_TOKEN"], bot.user.id) as nexobots:
        await nexobots.post_stats(server_count=len(bot.guilds), shard_count=bot.shard_count)


@post_stats.before_loop
async def before_post_stats():
    await bot.wait_until_ready()

Start the loop in your setup_hook with post_stats.start().

Not using JavaScript or Python? The API reference shows the same calls in plain HTTP.

Check whether someone voted

To give a reward for voting, ask us whether a user voted in the last 12 hours:

if (await nexobots.hasVoted(user.id)) {
  // Thank them.
}
async with Nexobots(os.environ["NEXOBOTS_TOKEN"], bot.user.id) as nexobots:
    if await nexobots.has_voted(user.id):
        ...  # Thank them.

React to votes with a webhook

Polling works, but a webhook is better: we send a request to your server the moment someone votes. Set the URL in your dashboard, which gives you a secret once. The URL must be public and use https.

Always check the signature, or anyone could fake votes by calling your URL. The SDKs do that for you. Give them the raw request body, before any JSON parsing:

import { createServer } from "node:http";
import { parseWebhook } from "@nexobots/sdk";

createServer((req, res) => {
  const chunks = [];
  req.on("data", (chunk) => chunks.push(chunk));
  req.on("end", () => {
    const vote = parseWebhook(process.env.NEXOBOTS_WEBHOOK_SECRET, Buffer.concat(chunks).toString(), req.headers["x-nexo-signature"]);
    if (!vote) {
      res.statusCode = 401;
      return res.end();
    }
    console.log(`${vote.user} voted (${vote.type})`);
    res.statusCode = 204;
    res.end();
  });
}).listen(3001);

In Python, it's parse_webhook(os.environ["NEXOBOTS_WEBHOOK_SECRET"], raw_body, request.headers.get("X-Nexo-Signature")), which returns None for a bad signature.

Answer quickly with a 2xx status, then do your work afterwards. Use the test button in your dashboard to send a test delivery and see the result in the delivery log.

The API reference has the full payload and the retry schedule.

Because a webhook sends you voters' Discord IDs, you handle that personal data under our Data Processing Agreement. Read it before you switch webhooks on.

Show your badge

Embed a live badge in your README or website:

[![Nexobots](https://api.nexobots.app/v1/widget/YOUR_CLIENT_ID.svg)](https://nexobots.app/bots/your-bot)

Keep your listing healthy

  • Update your description and changelog when you ship something.
  • Keep your bot online. Listings that look offline for 7 days get a warning, and they're archived after 30. You can resubmit once it's back.
  • Never pay for or fake votes. Suspicious votes aren't counted, and repeat offenders lose their ranking for the month.

Congratulations: you've gone from "what is a bot token?" to a listed bot.

Show your uptime

Send a heartbeat every 5 minutes, and your page shows how reliably your bot has been online. With the SDK, call startHeartbeat() in JavaScript or run_heartbeat() in Python. Without it, POST /v1/bots/:id/heartbeat with your API token does the same. Nexo Certified needs 7 days of measured uptime, and this counts.

Still stuck? Open a ticket and a mentor will take a look. We'll know which guide you were on.