Developers

Bots and webhooks for Lobus.

The full documentation for anyone who wants to build their own helpers: webhooks, bots, gateway, slash commands and the Node.js SDK.

Developers

Bots

Your own helpers for your server: they react to commands and messages.

Webhooks

Let other services post messages into your channels.

Slash commands

Type “/” in chat and trigger something quickly.

In the examples, <your-lobus-address> stands for the address of your Lobus instance. Replace it with your real address.

Overview

Lobus offers two ways to automate things. There is also a small bot SDK for Node.js.

WayWhat forSign-in
WebhooksSimply post messages into a channel (build status, alerts, feeds)Secret URL, no account needed
BotsReact to messages, offer slash commands, moderateBot token (lobus_bot_…)

Quick start: a webhook in two minutes

  1. In the server settings, open the Apps tab and create a webhook for the channel you want (give it a name).
  2. The secret address is shown only once. It looks like https://<your-lobus-address>/api/v1/hooks/<webhook-id>/<secret-part>. Treat it like a password.
  3. Send a message:
bash
curl -X POST "https://<your-lobus-address>/api/v1/hooks/<webhook-id>/<secret-part>" \
  -H "content-type: application/json" \
  -d '{"content":"Build #42 passed ✅"}'

Response on success: 204 No Content.

Rules for webhooks

  • Body (JSON, only these fields): content (text, up to 4000 characters) and optionally embeds (up to 10).
  • The sender name is fixed to the webhook name; it cannot be changed per message.
  • At most 10 webhooks per server.
  • Anyone who knows the URL can write to exactly that one channel. If it leaked: delete the webhook and create a new one.
  • At most 120 calls per minute per IP address (after that 429 with a wait time).

Embeds (structured messages)

Embeds contain text only and are allowed for bots and webhooks. No external images or links.

json
{
  "content": "",
  "embeds": [
    {
      "title": "Deployment",
      "description": "Version 1.4.2 is live.",
      "color": "#7c5cff",
      "fields": [
        { "name": "Duration", "value": "42 s", "inline": true },
        { "name": "Branch", "value": "main", "inline": true }
      ],
      "footer": "CI"
    }
  ]
}

Limits: at most 3 embeds per bot message, title 256 characters, description 2000, up to 10 fields, footer 128, 4000 characters in total.

Bots

Create and add a bot

  1. Open Settings → Dev portal (bots) and create an application.
  2. The token (lobus_bot_…) is shown only once. The server stores only a SHA-256 hash. If you lose it: “New token”.
  3. In the dev portal, add the bot to a server. You need the “Manage roles” permission there. The bot never gets more permissions than you; only the server owner can grant the administrator permission.
  4. Give the token to the bot process only as an environment variable, never in code, Git or chat.

Bots are normal members with a managed role. They only see channels their role allows, and are authorized and rate-limited like users. Resetting, deleting and adding a token is recorded in the log.

Authentication

Every request carries the header Authorization: Bot <token>.

Bots may: read servers, read, send, edit and delete channel messages, add reactions, send files, fetch a gateway ticket, remove, ban and time out members, assign roles and register their own slash commands. Everything else (friends, direct messages, profile, dev portal, server administration) is reserved for people.

Send messages

HTTP
POST /api/v1/channels/:channelId/messages
{ "content": "…", "embeds": [ … ] }

Real-time events (gateway)

  1. Get a ticket: POST /api/v1/gateway/ticket (valid for 30 seconds, single use).
  2. Open a WebSocket: wss://<your-lobus-address>/gateway?ticket=<ticket>.
  3. Events arrive as JSON { "t": "<type>", "d": { … } }. Important types: ready, message.create, message.update, message.delete, interaction.create, presence.update.
HTTP
POST /api/v1/gateway/ticket
wss://<your-lobus-address>/gateway?ticket=<ticket>
{ "t": "message.create", "d": { … } }

The SDK takes care of the ticket, the connection and automatic reconnecting with a back-off.

Slash commands

  • The bot registers its commands with PUT /api/v1/bot/commands (replaces all previous ones, at most 50). Names: a-z, 0-9, _, -. Options have the type string, integer or boolean.
  • Users type / and see suggestions, then /command value ….
  • The bot receives interaction.create on the gateway with a one-time token.
  • Reply: POST /api/v1/interactions/:id/:token/callback with { "content": "…", "embeds": [ … ] }. Valid for 15 minutes, at most 5 replies. No bot header is needed for this, only the token from the event.
json
[
  {
    "name": "wuerfeln",
    "description": "Rolls a number",
    "options": [
      { "name": "seiten", "description": "Number of sides", "type": "integer", "required": true }
    ]
  }
]
HTTP
POST /api/v1/interactions/:id/:token/callback
{ "content": "…", "embeds": [ … ] }

Bot SDK (Node.js)

No dependencies, Node 22 or newer (built-in fetch and WebSocket). The SDK lives in the Lobus project under packages/bot-sdk. It is not published as a package yet.

ts
import { Bot } from './packages/bot-sdk/src/index.ts';

const bot = new Bot({
  baseUrl: process.env.LOBUS_URL ?? '',
  token: process.env.LOBUS_BOT_TOKEN ?? '',
});

bot.on('ready', async () => {
  await bot.rest.setCommands([
    {
      name: 'wuerfeln',
      description: 'Rolls a number',
      options: [{ name: 'seiten', description: 'Number of sides', type: 'integer', required: true }],
    },
  ]);
});

bot.on('interaction.create', async (i) => {
  if (i.command !== 'wuerfeln') return;
  const seiten = Math.min(Math.max(Number(i.options.seiten) || 6, 2), 1000);
  const wurf = 1 + Math.floor(Math.random() * seiten);
  await bot.rest.respond(i, '', [
    { title: 'Roll', description: `${i.user.displayName} rolls a ${wurf} (W${seiten})`, color: '#7c5cff' },
  ]);
});

await bot.start();

Start:

bash
LOBUS_URL=https://<your-lobus-address> LOBUS_BOT_TOKEN=lobus_bot_… node bot.ts

The SDK sends the token only to the address you give it, keeps it in memory only, and catches errors in individual handlers without stopping the bot.

Errors

Errors come as JSON { "error": "<code>" } with a matching HTTP status:

StatusMeaning
400invalid input
401not signed in
403no permission
404not found (also when you are not allowed to see it)
409conflict (e.g. webhook limit)
429too many requests

Security at a glance

  • Tokens and webhook URLs are secrets: never in code, repositories or chats.
  • Bot tokens are stored on the server only as a hash.
  • Bots never have more permissions than the person who added them.
  • One-time interaction and gateway tokens expire quickly.

Not available yet