The gateway
A bot talks to ILLEST over one WebSocket, the same one the apps use. There is no separate REST API: every request is a frame on the socket, and its answer comes back on it. illest.py speaks it for you; this page is for writing a library of your own, or for reading what illest.py does.
Frames
Every frame is one JSON object, at most 1 MiB:
{ "v": 2, "op": "REQ", "id": "7", "t": "message.send", "d": { "channel_id": "...", "ciphertext": "..." } }| Field | What it holds |
|---|---|
v | the protocol's version, 2 |
op | what kind of frame it is |
id | on a request, any text of yours; its answer carries the same |
t | a request's action, or an event's name |
d | the body |
seq | on an event, its place in the session, for resuming |
ok | on an answer, whether it worked |
| Op |
|---|
HELLO |
IDENTIFY |
RESUME |
READY |
RESUMED |
INVALID_SESSION |
REQ |
RES |
DISPATCH |
HEARTBEAT |
HEARTBEAT_ACK |
ERROR |
A session
- Open the socket. The server sends
HELLOwith a nonce and the heartbeat interval (heartbeat_ms). - Send
IDENTIFYwith the session token, and a signature over the nonce made with the bot's device key. The server answersREADY, with who the bot is, the servers and channels it is in, and the encrypted groups it holds. - Send
HEARTBEATat the interval. A socket that stops answering is closed. - Send
REQframes; each gets aRESwith the sameid. Events arrive asDISPATCHframes. - After a drop, send
RESUMEwith the lastseqyou saw. The server replays what you missed and answersRESUMED, orINVALID_SESSION, after which youIDENTIFYagain.
A bot gets its session token by signing in with its bot token through bot.identify, which also registers its device key on the
first run (illest.py's auth.py).
Answers and errors
A refused request is a RES with ok: false and d: { "code": "...", "message": "..." }. illest.py raises the matching
exception: Forbidden, NotFound, RateLimited, MissingScope and so on.
| Code |
|---|
BAD_ENVELOPE |
UNSUPPORTED_VERSION |
FRAME_TOO_LARGE |
NOT_AUTHENTICATED |
ALREADY_AUTHENTICATED |
AUTH_FAILED |
UNKNOWN_ACTION |
BAD_REQUEST |
FORBIDDEN |
NOT_FOUND |
RATE_LIMITED |
STALE_EPOCH |
MESSAGE_EPOCH_STALE |
ROSTER_STALE |
RESET_COOLDOWN |
INTERNAL |
Events
What the server sends as DISPATCH, and the library's events each becomes. Most of what a bot reads (messages, edits, reactions,
commands, presses and forms) arrives sealed inside message.create and is opened on the bot's side. Events
lists every event with its arguments.
| Frame | Becomes |
|---|---|
message.create | on_interaction, on_message, on_message_delete, on_message_edit, on_raw_message_delete, on_raw_message_edit, on_raw_reaction_add, on_raw_reaction_remove, on_reaction_add, on_reaction_remove |
mls.welcome | on_group_join |
mls.commit | none |
mls.key_packages.low | none |
interaction.click | none |
guild.member.add | on_guild_join, on_member_join |
guild.member.remove | on_guild_remove, on_member_ban, on_member_remove, on_raw_member_remove |
guild.member.update | on_member_update |
guild.remove | on_guild_remove |
guild.delete | on_guild_remove |
guild.update | on_guild_channel_create, on_guild_channel_delete, on_guild_channel_update, on_guild_role_create, on_guild_role_delete, on_guild_role_update, on_guild_update |
guild.unban | on_member_unban |
channel.typing | on_raw_typing, on_typing |
message.redact | on_message_delete, on_message_redact, on_raw_message_delete |
user.update | on_user_update |
presence.update | on_presence_update |
voice.state | on_voice_state_update |
channel.pins.update | on_guild_channel_pins_update, on_private_channel_pins_update |
channel.stale | none |
Actions
What a bot may send as REQ, the scopes each needs and its rate limit: bot actions.