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/wsHandshake
1. Receive HELLO
Immediately after connecting the server sends an HELLO message with the heartbeat interval:
{
"op": 10,
"d": {
"heartbeatInterval": 41250
}
}2. Send IDENTIFY
Reply with an IDENTIFY message containing your bot token:
{
"op": 2,
"d": {
"token": "Bot YOUR_TOKEN_HERE"
}
}3. Receive READY
On successful authentication you receive a READY dispatch:
{
"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:
{ "op": 1, "d": null }The server responds with a heartbeat acknowledgement:
{ "op": 11 }If you miss heartbeats the server will close the connection.
Message Format
All messages follow this envelope:
| Field | Type | Description |
|---|---|---|
op | integer | Opcode (see table below) |
t | string | Event name (dispatch only, op: 0) |
s | integer | Sequence number (dispatch only) |
d | object | Payload data |
Opcodes
| Opcode | Name | Direction | Description |
|---|---|---|---|
0 | Dispatch | Server → Bot | An event was dispatched |
1 | Heartbeat | Bot → Server | Keepalive ping |
2 | Identify | Bot → Server | Authenticate |
6 | Resume | Bot → Server | Resume after reconnect |
10 | Hello | Server → Bot | Sent on connect |
11 | Heartbeat ACK | Server → Bot | Heartbeat acknowledged |
Close Codes
| Code | Meaning |
|---|---|
4000 | Unknown error — try reconnecting |
4001 | Unknown opcode |
4003 | Not authenticated |
4004 | Authentication failed — check your token |
4005 | Already authenticated |
4007 | Invalid sequence number |
4009 | Session 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.
{
"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).
{
"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:
{
"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)
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
}
})