The Hub bots

A bot is an app that chats in spaces: it welcomes people, answers commands, posts updates. It has its own account (with a BOT tag next to its name), and a program you run anywhere talks to The Hub for it through the API.

Making a bot

  1. Settings → Bots → Create bot. Copy the token it shows you. It's only shown once; New token makes another and switches the old one off.
  2. Add it to a space: Space settings → Bots, for anyone with Manage space. You can add your own bots anywhere you manage. Switch a bot to public (the switch on its card) to let other people add it to their spaces too.
  3. Run its program. tools/example-bot.php is a complete small bot to start from: `` php tools/example-bot.php --server https://your-site/voicelink/ --token vlb_… ``

A bot sees and does what its roles in each space allow, like anyone else. Give it a role in Space settings → Members if it needs more (to pin messages, for example).

The API

Every request goes to api.php?action=<name> with the token in a header:

Authorization: Bot vlb_…

(X-Bot-Token: vlb_… works too, for hosts that drop the Authorization header.) No cookies or CSRF token are needed. Send POST bodies as JSON with Content-Type: application/json. Every answer is JSON with "ok": true, or "ok": false and an "error" to show.

Hearing new messages: bot_events

GET api.php?action=bot_events&after=<message id> returns up to 100 new messages, oldest first, from every channel and direct message the bot can see (never its own), and last_id to pass as after next time.

Call it once without after when your bot starts: it returns no messages and the current last_id, so the bot doesn't answer things said before it was running. Then ask every second or two.

Each message has id, channel_id, server_id (null in a direct message), channel_type (text or dm), channel_name, author (id, username, display_name, bot, …), content, attachments, reply, reactions, created_at and edited_at.

Doing things

ActionMethodWhat to send
meGETThe bot's own profile, under user.
message_sendPOSTchannel_id, content (up to 4000 characters, Markdown like in the app), optional reply_to (a message id) and attachments (from upload).
message_editPOSTid, content. Its own messages only.
message_deletePOSTid. Its own, or anyone's with Manage messages.
reactPOSTmessage_id, emoji. Adds the reaction, or takes it away if it's already there.
typingPOSTchannel_id. Shows "… is typing" for a few seconds.
messagesGETchannel_id, optional before (a message id): the 50 messages before it, newest last.
pins / message_pinGET / POSTchannel_id / id: list pins, or pin and unpin (needs Manage messages in a space).
uploadPOSTA file as multipart form data. Send the file it returns in attachments.
user_profileGETuser_id, optional server_id.
dm_openPOSTuser_id: the direct-message channel with that person (their message settings apply).
syncGETThe same snapshot the app gets: spaces, channels, members, roles. Use server_id for one space's details.

Anything else (voice, settings, friends, joining or leaving spaces) answers "Bots can't use this part of the API".

Limits: a bot can send 5 messages every 5 seconds; more get a 429 answer, so wait a moment and try again.

Keeping the token safe

Anyone with the token can post as the bot. Keep it out of code you share (the example bot also reads it from the VOICELINK_BOT_TOKEN environment variable), and make a new one in Settings → Bots if it leaks. Deleting a bot takes it out of every space and switches its token off; its messages stay, shown as "Deleted bot".

This page is built from docs/BOTS.md in The Hub's source.