Sunflare Docs Beta

Build on Sunflare

Writing Bots

A Sunflare bot is a real user account: same permissions, same channels and DMs, same roles, authenticated by a token instead of a password. There's no separate bot API surface to learn: a bot calls the exact same REST routes the app itself does.

📡

There's no realtime gateway/websocket. A bot finds out about new messages by polling. The official SDK below does this for you (every 2s for watched channels, every 30s for the server/channel list).

Create a bot

From a server you manage: Server Settings → Bots → Create Bot. To create one that isn't tied to a specific server yet (useful if you're going to distribute it to other servers), use User Settings → Developer Portal → Create Bot instead.

Either way you'll get a token back exactly once. Copy it immediately, there's no way to view it again later (only regenerate, which invalidates the old one):

<botId>.<secret>

The Developer Portal is also where you regenerate a token or delete a bot account entirely (cascades: removes it from every server it's in).

Inviting a bot to a server

Every bot has an invite link:

https://sunflare.me/oauth2/authorize?client_id=<botId>

Opening it while logged in shows a consent screen listing servers you manage, and adds the bot to whichever one you pick. A server owner/manager can also skip this and add a bot directly from Server Settings → Bots if they already have its ID.

Authenticating requests

Every request needs an Authorization header in this exact form. Note the literal word Bot, not Bearer:

Authorization: Bot <botId>.<secret>

From there, a bot can call any normal authenticated route. There's no curated bot-only subset. In practice you'll mostly want:

RouteWhat it does
GET /profileConfirm the token works and see the bot's own identity
GET /api/serversServers this bot belongs to
GET /api/servers/:id/channelsA server's channel list
GET /api/channels/:id/messagesRecent messages in a channel
POST /api/channels/:id/messagesSend a message: { text }
PATCH /api/channels/:id/messages/:msgIdEdit a message the bot sent
DELETE /api/channels/:id/messages/:msgIdDelete a message (needs Manage Messages if not the bot's own)
GET / POST /api/dms and /api/dms/:id/messagesDirect messages, same shape as channels

A bot's permissions come from whatever roles it holds in a server. Assign it a role the same way you would a person, under Server Settings → Roles. A bot can never be a server's owner.

Rate limits

Bots share the same general API limit as everyone else: 1200 requests/minute per IP. There's no separate, higher bot allowance. Plan polling intervals accordingly if you're running several bots from one machine/IP.

Quick start with the official SDK

bots/sunflare-bot.js in the repo wraps the polling and message routes into an event emitter:

const SunflareBot = require('./sunflare-bot');

const bot = new SunflareBot(process.env.SUNFLARE_BOT_TOKEN, {
  baseUrl: 'https://sunflare.me'
});

bot.on('ready', () => console.log('Bot is ready'));

bot.on('message', async (msg) => {
  if (msg.text === '!ping') {
    await bot.sendMessage(msg.channelId, 'Pong!');
  }
});

bot.login();

Methods available on a SunflareBot instance: login(), destroy(), getServers(), getChannels(serverId), getVoicePresence(serverId), getDms(), getMessages(channelId), getDmMessages(dmId), sendMessage(channelId, text), sendDmMessage(dmId, text), editMessage/deleteMessage, editDmMessage/deleteDmMessage, and watchChannel/watchDm (starts the 2s poll that emits 'message' for that conversation) with matching unwatch* calls.

A minimal runnable example lives at bots/example-bot.js; a more advanced sample doing voice/audio playback via WebRTC is under bots/music-bot/ (see its own README; there's no built-in voice SDK, it hand-rolls the WebRTC side with werift/ffmpeg/yt-dlp).

Building without the SDK

The SDK is a thin convenience wrapper. Nothing stops you calling the REST routes directly from any language:

curl -X POST https://sunflare.me/api/channels/CHANNEL_ID/messages \
  -H "Authorization: Bot YOUR_BOT_ID.YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"text":"Hello from curl"}'

Good to know