Skip to content

WebSocket Gateway

The WebSocket gateway lets your bot receive real-time events — new messages, member activity, command invocations, etc.

Connecting

Connect to:

wss://app.fluffwire.com/ws

Handshake

1. Receive HELLO

Immediately after connecting the server sends an HELLO message with the heartbeat interval:

json
{
  "op": 10,
  "d": {
    "heartbeatInterval": 41250
  }
}

2. Send IDENTIFY

Reply with an IDENTIFY message containing your bot token:

json
{
  "op": 2,
  "d": {
    "token": "Bot YOUR_TOKEN_HERE"
  }
}

3. Receive READY

On successful authentication you receive a READY dispatch:

json
{
  "op": 0,
  "t": "READY",
  "s": 1,
  "d": {
    "sessionId": "...",
    "user": { "id": "...", "username": "MyBot", "isBot": true }
  }
}

If authentication fails the connection is closed with code 4004.

Heartbeat

Send a heartbeat every heartbeatInterval milliseconds (41 250 ms ≈ 41 seconds) to keep the connection alive:

json
{ "op": 1, "d": null }

The server responds with a heartbeat acknowledgement:

json
{ "op": 11 }

If you miss heartbeats the server will close the connection.

Message Format

All messages follow this envelope:

FieldTypeDescription
opintegerOpcode (see table below)
tstringEvent name (dispatch only, op: 0)
sintegerSequence number (dispatch only)
dobjectPayload data

Opcodes

OpcodeNameDirectionDescription
0DispatchServer → BotAn event was dispatched
1HeartbeatBot → ServerKeepalive ping
2IdentifyBot → ServerAuthenticate
6ResumeBot → ServerResume after reconnect
10HelloServer → BotSent on connect
11Heartbeat ACKServer → BotHeartbeat acknowledged

Close Codes

CodeMeaning
4000Unknown error — try reconnecting
4001Unknown opcode
4003Not authenticated
4004Authentication failed — check your token
4005Already authenticated
4007Invalid sequence number
4009Session timed out — reconnect

Events

Dispatched events have op: 0. The event name is in the t field.

MESSAGE_CREATE

A new message was sent to a channel the bot is a member of.

json
{
  "op": 0, "t": "MESSAGE_CREATE", "s": 2,
  "d": {
    "id": "...",
    "channelId": "...",
    "content": "Hello!",
    "author": { "id": "...", "username": "SomeUser" },
    "createdAt": "2025-01-01T00:00:00Z"
  }
}

MESSAGE_UPDATE

A message was edited.

MESSAGE_DELETE

A message was deleted. Payload: { "id": "...", "channelId": "..." }.

SERVER_MEMBER_ADD / SERVER_MEMBER_REMOVE

A user joined or left a server.

COMMAND_INVOKE

A user invoked one of the bot's slash commands (see Slash Commands).

json
{
  "op": 0, "t": "COMMAND_INVOKE", "s": 5,
  "d": {
    "commandId": "...",
    "commandName": "ping",
    "channelId": "...",
    "userId": "...",
    "serverId": "...",
    "options": { "message": "hello" }
  }
}

PRESENCE_UPDATE

A user's online status changed.

Reconnecting

If the connection drops, reconnect and send a RESUME message with your last sequence number:

json
{
  "op": 6,
  "d": {
    "token": "Bot YOUR_TOKEN_HERE",
    "sessionId": "...",
    "seq": 42
  }
}

If the session is still valid, missed events will be replayed. Otherwise you will receive a new READY event.

Example (Node.js)

typescript
import WebSocket from 'ws'

const TOKEN = process.env.FLUFFWIRE_BOT_TOKEN!
let seq = 0

const ws = new WebSocket('wss://app.fluffwire.com/ws')

ws.on('message', (raw) => {
  const msg = JSON.parse(raw.toString())

  if (msg.s) seq = msg.s

  switch (msg.op) {
    case 10: // HELLO
      setInterval(() => ws.send(JSON.stringify({ op: 1, d: null })), msg.d.heartbeatInterval)
      ws.send(JSON.stringify({ op: 2, d: { token: `Bot ${TOKEN}` } }))
      break

    case 0: // DISPATCH
      if (msg.t === 'MESSAGE_CREATE') {
        console.log(`[${msg.d.channelId}] ${msg.d.author.username}: ${msg.d.content}`)
      }
      break
  }
})

Licensed under CC BY-NC-SA 4.0.