Strafe.chat Developers Open Strafe

Strafe Developer Documentation

Build bots that live in spaces, and applications that let people sign in with Strafe. Both go through the same two doors: a REST API and a real-time WebSocket gateway. Everything on this site describes the instance you are reading it on - the addresses in the sidebar are this instance's own.

What you can build#

You want to…UseStart with
Run a bot that reads and posts messages in spacesA bot - an application's bot account, authenticated with a bot tokenBots
Let people log in to your site or app with their Strafe accountOAuth2 - the authorization code grant with the identify / email / spaces scopesOAuth2
Let a bot add people to a space from your own websiteOAuth2 with the spaces.join scope, plus a bot with Create InviteOAuth2 › spaces.join
Let anyone add your bot to their space with a linkAn install link with the bot scope and a permissions valueApplications › Install links

Quick start#

  1. Open Settings → Developers in the Strafe client and create an application. You get a client ID and a client secret (shown once).
  2. Add a bot to the application. You get a bot token (shown once). The bot's user ID is the same as the application's client ID.
  3. Add the bot to a space you manage with the Add to a space button, or share the link the URL generator builds.
  4. Talk to the API with Authorization: Bot <token>, and connect to the gateway with the same header to receive messages as they happen.
bash
# Who am I?
curl -H "Authorization: Bot $BOT_TOKEN" <API>/users/@me

# Say hello in a room
curl -X POST -H "Authorization: Bot $BOT_TOKEN" -H "Content-Type: application/json" \
  -d '{"plaintext":"Hello from my bot!"}' \
  <API>/rooms/ROOM_ID/messages

Replace <API> with this instance's API base: https://your-instance.example/api.

This instance#

URL
Web client (and the OAuth2 consent page at /oauth2/authorize)https://your-instance.example
REST API basehttps://your-instance.example/api
Gateway (WebSocket)wss://your-instance.example/gateway/events
CDN (avatars, icons, attachments, emoji)https://your-instance.example/cdn

On a standard deployment the API is served under /api and the gateway under /gateway of the instance's domain. Paths in this documentation are relative to the API base: GET /users/@me means GET <API>/users/@me.

Authentication#

Every request carries one credential in the Authorization header. Nothing is read from cookies or query strings.

HeaderWhoGets
Authorization: Bot <bot token>A botEverything the bot account may do - the same endpoints a person's client uses, gated by the bot's permissions in each space
Authorization: Bearer <access token>An application acting for a user who authorized itOnly the endpoints its scopes allow (see OAuth2 › Scopes); anything else is 403 insufficient_scope
Authorization: Bearer <session token>The Strafe client itselfA person's full account. Not for applications: never ask a user for their session token

The gateway accepts the same Bot header on the WebSocket handshake.

Conventions#

  • IDs are strings. Every id ("2105141069376131072") is a 64-bit snowflake sent as a JSON string, because JavaScript numbers cannot hold it. Send ids back as strings too.
  • Timestamps are RFC 3339 / ISO 8601 in UTC: "2026-09-30T03:44:45.361Z".
  • Permissions are integer bitmasks (see Permissions). They fit comfortably in a JavaScript number.
  • JSON in, JSON out. Send Content-Type: application/json. The one exception is the OAuth2 token endpoint, which also takes a form body as the standard requires, and file uploads, which are multipart/form-data.
  • Errors are {"error": "message"} with a matching HTTP status (400 bad input, 401 bad or missing credentials, 403 not allowed, 404 not found, 409 conflict, 429 slow down). OAuth2 endpoints use the RFC 6749 error codes (invalid_grant, invalid_scope, …) and may add an error_description.
  • Rate limits are per endpoint group and return 429 with a Retry-After header when exceeded. Slowmode in a room returns 429 with retry_after seconds in the body. See REST › Rate limits.
  • End-to-end encryption. Private messages are end-to-end encrypted by default and space rooms can opt in. A bot cannot read or write in an encrypted room - messages there arrive with ciphertext and no plaintext. See Bots › Encryption.

Vocabulary#

Strafe borrows Discord's interaction model with its own names. If you have written a Discord bot, this table is the translation:

StrafeDiscordNotes
SpaceServer / guildspaces in every path and payload
RoomChannelSpace text and voice rooms, and private messages, are all rooms
SectionCategoryA room of type 5 that groups other rooms
PM / group PMDM / group DMRooms of type 1 and 2; end-to-end encrypted by default
Member, role, invite, emoji, reactionsame