Docs
Bots
Bots are self-hosted integrations. You run the code, Disband relays messages to and from it. Disband never hosts or executes your bot's code.
How it works
- Create a bot in Settings → Botsand pick the scopes it needs. You get a token back — it's shown once.
- In Settings → Bots, generate an invite link for the server you want the bot to join, and send it to that server's owner.
- The owner opens the link and approves. The bot becomes a member of the server.
- You run the client library somewhere (a server, a cloud function, your laptop) and it connects to Disband with the token.
Scopes
A bot's reach in a server is the intersection of the scopes you requested when creating it and the scopes the owner approved for that specific server:
| Scope | Description |
|---|---|
| messages.read | Receive message events on the gateway and read messages/channels. |
| messages.write | Send and reply to messages in channels the bot can see. |
| members.read | List the members of servers the bot has joined. |
| channels.manage | Create, rename, and delete channels — also needs the manage_channels role in the server. |
Client libraries
The official clients are token-authenticated and have zero runtime dependencies.
JavaScript
Works from Node.js 18+, Deno, Bun, and the browser. Install from this repo:
npm install /path/to/packages/bot
import { Client } from "@disband/bot";
const client = new Client({ token: process.env.DISBAND_BOT_TOKEN });
client.on("ready", (me) => console.log(`Logged in as ${me.name}`));
client.on("messageCreate", async (message) => {
if (message.author?.is_bot) return;
if (message.content !== "!ping") return;
await message.reply("pong");
});
await client.connect();Python
Standard library only (threading + urllib). Install from this repo:
pip install ./packages/disband-bot-python
from disband_bot import Client
client = Client(token=DISBAND_BOT_TOKEN)
@client.on("messageCreate")
def handle(message):
if message.author_is_bot:
return
if message.content == "!ping":
message.reply("pong")
client.run()API
All endpoints take Authorization: Bot <token>. Errors return JSON with an error field and a 4xx/5xx status.
Endpoints
GET/api/v1/gateway?timeout=20Long-poll for message events (messageCreate / messageUpdate / messageDelete).
POST/api/v1/channels/:id/messagesSend a message. Body: { content, reply_to_id }.
GET/api/v1/channels/:id/messagesRead messages. Query: limit, before.
GET/api/v1/servers/:id/channelsList channels.
GET/api/v1/servers/:id/membersList members.
POST/api/v1/servers/:id/channelsCreate a channel. Body: { name, type, category_id }.
PATCH/api/v1/channels/:idRename a channel. Body: { name }.
DELETE/api/v1/channels/:idDelete a channel.
POST/api/v1/servers/:id/leaveRemove the bot from a server.
POST/api/v1/bots/:botId/invitesGenerate an invite. Body: { server_id, scopes }.
Message payload
{
"id": "…",
"channel_id": "…",
"server_id": "…",
"author": { "id": "…", "username": "…", "display_name": "…", "avatar_url": "…", "is_bot": false },
"content": "Deploy finished",
"reply_to_id": null,
"mentions": [],
"attachment_url": null,
"attachment_type": null,
"created_at": "2026-01-01T00:00:00Z",
"edited_at": null,
"display_id": 1234
}Limits & safety
- Up to 5 bots per account. A bot can be revoked at any time, which kills its token.
- Messages up to 4,000 characters. Bots need the
mention_everyonerole permission to use@everyone. - Only a server's owner can approve a bot invite. Invites expire after 7 days.
- Bot tokens are hashed at rest; the raw token is never stored or retrievable.
- Bots can never reach the database directly — every action goes through scoped API endpoints.