Gateway events
A Dispatch tells a Gateway session that something changed or answers one of its commands. It has opcode 0, an event name in t and the payload in d.
Dispatch envelope
Section titled “Dispatch envelope”| Field | Type | Description |
|---|---|---|
| op | integer | Value 0 |
| t | string | Uppercase event name |
| s | integer | Non-negative session sequence |
| d | any | Payload defined for the event in t |
{ "op": 0, "t": "MESSAGE_CREATE", "s": 17, "d": { }}Ready has sequence 1 and each live Dispatch after it adds one. Replayed Dispatches keep their original sequence and can have gaps. The sequence counts Dispatches for one session and says nothing about order across shards or HTTP requests.
Dispatch delivery
Section titled “Dispatch delivery”Event filtering decides which sessions receive each Dispatch. A user session without the CHANNEL_THREADS flag also gets reduced payloads and no thread events.
Most guild events have a guild_id. Guild Create, Guild Sync and Guild Delete use id, and Guild Counts Update and Channel Member Counts Update put guild_id on each entry.
The session that made a change receives the Dispatch like any other session. The one exception is a guild-channel reaction, where the request's session_id excludes that session from Message Reaction Add and Message Reaction Remove.
Resume replays every Dispatch except Ready and the Guild Create and Guild Delete burst a bot gets after Ready. These events are live only and are never replayed.
Limits and rate limits explains when an oversized Dispatch is not kept.
Dispatch events
Section titled “Dispatch events”| Event | Description |
|---|---|
| Ready | The initial session state after a successful Identify |
| Resumed | Replay after a Resume is finished |
| Sessions Replace | The account's live sessions changed |
| Auth Session Change | A password change replaced the authentication session |
| Rate Limited | A bot asked for a full member list too often |
| User Update | The current user's account record changes |
| User Settings Update | The current user's account-wide settings change |
| User Guild Settings Update | One guild notification record changes |
| User Note Update | The current user writes or clears a private note |
| User Pinned DMs Update | The current user's pinned private channel set is replaced |
| User Connections Update | The current user's external connection set is replaced |
| WebAuthn Credentials Update | The current user's WebAuthn credential set is replaced |
| Relationship Add | The current user gains a relationship |
| Relationship Update | One of the current user's relationships changes |
| Relationship Remove | The current user loses a relationship |
| Saved Message Create | The current user saves a message |
| Saved Message Delete | The current user unsaves a message |
| Recent Mention Delete | The current user removes a recent mention |
| Favorite Meme Create | The current user saves a meme |
| Favorite Meme Update | One of the current user's memes changes |
| Favorite Meme Delete | The current user deletes a meme |
| Guild Create | A guild becomes available to the session |
| Guild Sync | A subscribed session receives the guild's full current state again |
| Guild Update | A guild's configuration changes |
| Guild Delete | A guild leaves the session's visibility or becomes unavailable |
| Guild Role Create | A role is created in a guild |
| Guild Role Update | One role changed |
| Guild Role Update Bulk | Several roles changed at once |
| Guild Role Delete | A role is deleted from a guild |
| Guild Emojis Update | A guild's emojis change |
| Guild Stickers Update | A guild's stickers change |
| Channel Create | A channel becomes visible to the session |
| Channel Update | A visible channel changes |
| Channel Update Bulk | One operation changes several channels together |
| Channel Delete | A channel leaves the session's visibility |
| Channel Recipient Add | A user joins a group direct message the session belongs to |
| Channel Recipient Remove | A user leaves a group direct message the session belongs to |
| Webhooks Update | The webhook set of a viewable guild channel changes |
| Invite Create | An invite is created |
| Invite Delete | An invite is deleted |
| Thread Create | A thread is created or the session joins one |
| Thread Update | A visible thread changes |
| Thread Delete | A thread is deleted |
| Thread List Sync | The session's active thread set is replaced |
| Thread Member Update | The session's own thread membership changes |
| Thread Members Update | Users join or leave a thread |
| Thread Member List Update | A subscribed thread member list changed |
| Forum Unreads | Unread counts for forum posts are returned |
| Guild Member Add | A user becomes a member of a connected guild |
| Guild Member Update | A member's guild state or public user representation changes |
| Guild Member Remove | A user stops being a member of a connected guild |
| Guild Members Chunk | The answer to Request Guild Members |
| Guild Member List Update | A subscribed member list changed |
| Guild Audit Log Entry Create | An audit log entry is written in a guild |
| Guild Ban Add | A guild ban is created |
| Guild Ban Remove | A guild ban is removed |
| Presence Update | One visible presence changes |
| Presence Update Bulk | Online presences of a guild that was unavailable |
| Passive Updates | Channel last_message_id values or voice states changed for one passive session |
| Message Create | A visible message is created |
| Message Update | A message changed |
| Message Delete | One visible message is deleted |
| Message Delete Bulk | Several messages in one channel are deleted together |
| Message ACK | The current user's read state advances for a channel |
| Message Reaction Add | A user adds a reaction to a message |
| Message Reaction Add Many | Several reactions grouped into one event |
| Message Reaction Remove | One user's reaction is removed from a message |
| Message Reaction Remove All | Every reaction is removed from a message at once |
| Message Reaction Remove Emoji | Every reaction using one emoji is removed from a message |
| Typing Start | A visible user begins typing in a channel |
| Channel Pins Update | A channel's most recent pin time changes |
| Channel Pins ACK | The current user acknowledges a channel's pins |
| Voice State Update | A guild or call participant's voice state changes |
| Voice Server Update | The session receives or replaces its own voice grant |
| Voice Signal | A signaling message from another peer-to-peer connection |
| Entrance Sound Play | A participant's entrance sound plays in a voice channel |
| Call Create | A private channel call begins or becomes visible |
| Call Update | The ringing set, participant roster, or region of a call changes |
| Call Delete | A call ends or becomes unavailable |
| Guild Counts Update | Member and online counts are returned for connected guilds |
| Channel Member Counts Update | Per-channel member and online counts are returned for one guild |
Session and current user
Section titled “Session and current user”The session's initial state, sent once after a successful Identify.
| Field | Type | Description |
|---|---|---|
| session_id | string | Identifier for Resume |
| version | integer | Gateway API version the connection negotiated, always 1 |
| user | user object | The authenticated account in its private representation |
| guilds1 | array[guild ready object] | The session's guilds |
| private_channels | array[channel object] | Direct message and group direct message channels |
| relationships2 | array[relationship object] | The account's relationships |
| presences3 | array[presence object] | Visible presences at connection time |
| users2 | array[partial user object] | Users referenced by the payload |
| sessions | array[session presence object] | Every live session of the account, after a combined all entry |
| read_states | array[read state object] | Per-channel read state |
| user_settings | ?user settings object | Account-wide settings |
| user_guild_settings | array[user guild settings object] | Per-guild notification settings |
| notes | map[snowflake, string] | Private notes keyed by user ID |
| pinned_dms | array[snowflake] | Pinned private channel IDs |
| favorite_memes | array[meme object] | Saved memes |
| webauthn_credentials | array[WebAuthn credential object] | Registered WebAuthn credentials |
| rtc_regions | array[RTC region object] | Voice regions, nearest first |
| country_code | string | Country of the connecting address, US when unknown |
| latitude? | string | Latitude of the connecting address as a decimal string |
| longitude? | string | Longitude of the connecting address as a decimal string |
| auth_session_id_hash? | string | Base64url hash identifying the authentication session |
| shard? | array[integer] | The accepted [shard_id, shard_count] pair, when Identify sent one |
| _timings? | object | HTTP-side timing breakdown, only for a staff account |
| _timings_gw? | object | Gateway-side timing breakdown, only for a staff account |
1 On a bot session every entry is {"id": "...", "unavailable": true}, and a Guild Create or Guild Delete for each one follows Ready
2 Relationships in Ready have no user, and each guild member's user has only id. The full accounts are in users. A bot gets an empty users, its Guild Create burst after Ready has members with the same {"id": "..."} user, and it fetches the accounts with Request Guild Members. A later Guild Create and every Guild Sync have full members.
3 Always empty for a bot session
Shortly after Ready, the session gets a Call Create for each private channel with an active call.
Guild ready object
Section titled “Guild ready object”The guild state in Ready, Guild Create and Guild Sync.
| Field | Type | Description |
|---|---|---|
| id | snowflake | Guild ID |
| properties | guild object | Guild record without its roles, channels, emojis, stickers or members |
| roles | array[guild role object] | Every role in the guild |
| channels | array[channel object] | Channels the session can view |
| emojis | array[guild emoji object] | Every emoji in the guild |
| stickers | array[guild sticker object] | Every sticker in the guild |
| members1 | array[guild member object] | The members the session needs immediately |
| member_count | integer | Total member count |
| online_count | integer | Members with a live session and a status other than offline or invisible |
| presences2 | array[presence object] | Always an empty array |
| voice_states | array[voice state object] | Voice states in channels the session can view |
| joined_at | ?ISO8601 timestamp | When the account joined the guild, null when it is not a member |
| unavailable? | boolean | Whether the guild is unavailable |
| visiting? | boolean | Whether the account is visiting the guild without being a member |
| unavailable_hidden? | boolean | Whether an unavailable guild is hidden from the client |
| threads?3 | array[thread object] | Active threads, as Guild threads describes |
1 Only the session's own member and the members in voice_states. Use Request Guild Members or a member list from Lazy Request for the rest
2 Presences arrive as Presence Update and Presence Update Bulk
3 Only for a session with thread access
An unavailable guild has only id, unavailable: true and, when hidden, unavailable_hidden: true.
Session presence object
Section titled “Session presence object”| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier, or all for the combined entry |
| status | string | online, idle, dnd, invisible or offline |
| afk | boolean | Whether the session is away |
| mobile | boolean | Whether the session is mobile |
The first entry is always all, with the account's combined status.
WebAuthn credential object
Section titled “WebAuthn credential object”| Field | Type | Description |
|---|---|---|
| id | string | Credential ID |
| name | string | Credential name |
| created_at | ISO8601 timestamp | When the credential was registered |
| last_used_at | ?ISO8601 timestamp | When the credential was last used |
| rp_id | string | The domain the passkey was created for, as in the WebAuthn credential object |
RTC region object
Section titled “RTC region object”| Field | Type | Description |
|---|---|---|
| id | string | Region ID |
| name | string | Human-readable region name |
| emoji | string | Region emoji |
The first entry is always automatic, which lets Fluxer pick the region. The rest are sorted by distance from the latitude and longitude in the Identify properties, or by ID when those are missing.
RESUMED
Section titled “RESUMED”Sent after a successful Resume has replayed the missed Dispatches. Its s is the current sequence and the next live Dispatch adds one.
| Field | Type | Description |
|---|---|---|
| _timings_gw? | object | Gateway-side timing breakdown, only for a staff account |
SESSIONS_REPLACE
Section titled “SESSIONS_REPLACE”The account's live sessions changed. The payload is an array of every session presence object, and it replaces the sessions list from Ready.
AUTH_SESSION_CHANGE
Section titled “AUTH_SESSION_CHANGE”A password change replaced the account's authentication session.
| Field | Type | Description |
|---|---|---|
| old_auth_session_id_hash | string | Base64url hash of the replaced authentication session |
| new_auth_session_id_hash | string | Base64url hash of the new authentication session |
Fluxer closes the Gateway sessions of the old authentication session before it sends this event, and they never receive it.
RATE_LIMITED
Section titled “RATE_LIMITED”A bot sent Request Guild Members for the full member list of a guild more than once in 30 seconds. Only the requesting session receives it.
| Field | Type | Description |
|---|---|---|
| opcode | integer | The refused opcode, always 8 |
| retry_after | number | Seconds until you can retry |
| meta | object | guild_id, plus nonce when the request had one |
USER_UPDATE
Section titled “USER_UPDATE”The current user's account changed. The payload is the user object in its private representation.
USER_SETTINGS_UPDATE
Section titled “USER_SETTINGS_UPDATE”The current user's settings changed. The payload is the user settings object.
USER_GUILD_SETTINGS_UPDATE
Section titled “USER_GUILD_SETTINGS_UPDATE”The notification settings for one guild changed. The payload is that guild's user guild settings object.
USER_NOTE_UPDATE
Section titled “USER_NOTE_UPDATE”The current user wrote or cleared a private note.
| Field | Type | Description |
|---|---|---|
| id | snowflake | User the note is about |
| note | string | Note text, empty when cleared |
USER_PINNED_DMS_UPDATE
Section titled “USER_PINNED_DMS_UPDATE”The pinned private channels changed. The payload is an array of every pinned channel ID in order, and it replaces pinned_dms from Ready.
USER_CONNECTIONS_UPDATE
Section titled “USER_CONNECTIONS_UPDATE”The current user's external connections changed.
| Field | Type | Description |
|---|---|---|
| connections | array[connection object] | Every connection on the account |
WEBAUTHN_CREDENTIALS_UPDATE
Section titled “WEBAUTHN_CREDENTIALS_UPDATE”The current user's passkeys changed. The payload is an array of every WebAuthn credential object, and it replaces webauthn_credentials from Ready.
RELATIONSHIP_ADD
Section titled “RELATIONSHIP_ADD”The current user has a new relationship.
| Field | Type | Description |
|---|---|---|
| id | snowflake | The other user's ID |
| type | integer | Relationship type |
| user | partial user object | The other user |
| since? | ISO8601 timestamp | When the relationship was created |
| nickname | ?string | Private nickname for the other user |
| share_voice_activity | boolean | Whether the current user shares voice activity with this friend |
| friend_shares_voice_activity1 | boolean | Whether the other user shares voice activity with the current user |
1 Only accurate in a Relationship Update sent by Modify voice activity sharing. List relationships always has the real value.
RELATIONSHIP_UPDATE
Section titled “RELATIONSHIP_UPDATE”A relationship changed. The payload has the same fields as Relationship Add.
RELATIONSHIP_REMOVE
Section titled “RELATIONSHIP_REMOVE”A relationship ended.
| Field | Type | Description |
|---|---|---|
| id | snowflake | The other user's ID |
SAVED_MESSAGE_CREATE
Section titled “SAVED_MESSAGE_CREATE”The current user saved a message. The payload is the message object.
SAVED_MESSAGE_DELETE
Section titled “SAVED_MESSAGE_DELETE”The current user unsaved a message.
| Field | Type | Description |
|---|---|---|
| message_id | snowflake | The message that is no longer saved |
RECENT_MENTION_DELETE
Section titled “RECENT_MENTION_DELETE”The current user removed a message from their recent mentions.
| Field | Type | Description |
|---|---|---|
| message_id | snowflake | The message removed from recent mentions |
FAVORITE_MEME_CREATE
Section titled “FAVORITE_MEME_CREATE”The current user saved a meme. The payload is the meme object.
FAVORITE_MEME_UPDATE
Section titled “FAVORITE_MEME_UPDATE”One of the current user's memes changed. The payload is the meme object.
FAVORITE_MEME_DELETE
Section titled “FAVORITE_MEME_DELETE”The current user deleted a meme.
| Field | Type | Description |
|---|---|---|
| meme_id | snowflake | The deleted meme |
Guilds and channels
Section titled “Guilds and channels”GUILD_CREATE
Section titled “GUILD_CREATE”A guild became available to the session, for example after joining it or when an unavailable guild recovers. The payload is a guild ready object.
Replace your stored roles, channels, emojis, stickers, voice_states and threads for the guild with the new arrays. members is partial, and you add or update those members and keep the others.
A later Guild Create without visiting means the account joined.
GUILD_SYNC
Section titled “GUILD_SYNC”The guild's full state again, sent after a Lazy Request asks for a sync or switches the guild between active and passive. The payload is a guild ready object, handled like Guild Create.
GUILD_UPDATE
Section titled “GUILD_UPDATE”A guild's settings changed. The payload is the guild object with guild_id added. An unavailable guild sends no other event.
GUILD_DELETE
Section titled “GUILD_DELETE”The session lost a guild, or the guild became unavailable.
| Field | Type | Description |
|---|---|---|
| id | snowflake | Guild ID |
| guild_id?1 | snowflake | Repeats id |
| unavailable? | boolean | True when the guild is temporarily unavailable |
| unavailable_hidden? | boolean | True when an unavailable guild is hidden from the client |
1 Only when the guild itself was deleted
Without unavailable, delete everything you store for the guild. With unavailable: true, keep it as unavailable until a Guild Create arrives.
GUILD_ROLE_CREATE
Section titled “GUILD_ROLE_CREATE”A role was created.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the role belongs to |
| role | guild role object | The created role |
GUILD_ROLE_UPDATE
Section titled “GUILD_ROLE_UPDATE”One role changed.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the role belongs to |
| role | guild role object | The updated role |
GUILD_ROLE_UPDATE_BULK
Section titled “GUILD_ROLE_UPDATE_BULK”Several roles changed at once, usually in a reorder.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the roles belong to |
| roles | array[guild role object] | Every changed role |
GUILD_ROLE_DELETE
Section titled “GUILD_ROLE_DELETE”A role was deleted.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the role belonged to |
| role_id | snowflake | The deleted role |
GUILD_EMOJIS_UPDATE
Section titled “GUILD_EMOJIS_UPDATE”A guild's emojis changed. Replace your stored emojis with the array.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the emojis belong to |
| emojis | array[guild emoji object] | Every emoji in the guild |
GUILD_STICKERS_UPDATE
Section titled “GUILD_STICKERS_UPDATE”A guild's stickers changed. Replace your stored stickers with the array.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the stickers belong to |
| stickers | array[guild sticker object] | Every sticker in the guild |
CHANNEL_CREATE
Section titled “CHANNEL_CREATE”A channel was created or the session can see it for the first time. The payload is the channel object.
CHANNEL_UPDATE
Section titled “CHANNEL_UPDATE”A visible channel changed. The payload is the channel object.
CHANNEL_UPDATE_BULK
Section titled “CHANNEL_UPDATE_BULK”Several channels changed at once, usually in a reorder. Each session gets only the channels it can view.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the channels belong to |
| channels | array[channel object] | Every changed channel |
CHANNEL_DELETE
Section titled “CHANNEL_DELETE”A channel was deleted or the session can no longer see it. The payload is the channel object as it was before. Remove every thread whose parent_id is the channel yourself, because Fluxer sends no Thread Delete for them.
CHANNEL_RECIPIENT_ADD
Section titled “CHANNEL_RECIPIENT_ADD”A user joined a group direct message the session is in.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Group direct message channel |
| user | partial user object | The user that joined |
CHANNEL_RECIPIENT_REMOVE
Section titled “CHANNEL_RECIPIENT_REMOVE”A user left a group direct message the session is in.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Group direct message channel |
| user | partial user object | The user that left |
WEBHOOKS_UPDATE
Section titled “WEBHOOKS_UPDATE”A guild channel's webhooks changed, including when a channel follow starts or ends. The event has no webhook data. Fetch the list with List channel webhooks.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the channel belongs to |
| channel_id | snowflake | Channel whose webhooks changed |
INVITE_CREATE
Section titled “INVITE_CREATE”An invite was created. The payload is the invite object with its invite metadata. A guild invite goes to sessions with MANAGE_CHANNELS on its channel, and a group direct message invite goes to every recipient.
INVITE_DELETE
Section titled “INVITE_DELETE”An invite was deleted. It goes to the same sessions as Invite Create.
| Field | Type | Description |
|---|---|---|
| code | string | The deleted invite code |
| channel_id? | snowflake | Channel the invite pointed at |
| guild_id? | snowflake | Guild the invite belonged to, absent for a group direct message invite |
Members and moderation
Section titled “Members and moderation”GUILD_MEMBER_ADD
Section titled “GUILD_MEMBER_ADD”A user joined a guild. The payload is the guild member object with guild_id added.
GUILD_MEMBER_UPDATE
Section titled “GUILD_MEMBER_UPDATE”A member or their public profile changed. The payload is the guild member object with guild_id added.
GUILD_MEMBER_REMOVE
Section titled “GUILD_MEMBER_REMOVE”A user is no longer a member of a guild. Fluxer also sends a Thread Members Update for each thread they were in.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the user left |
| user | object | The user, with id only |
GUILD_MEMBERS_CHUNK
Section titled “GUILD_MEMBERS_CHUNK”The answer to Request Guild Members. A request that matches nobody still gets one chunk with an empty members.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the members belong to |
| members | array[guild member object] | Up to 1,000 members |
| chunk_index | integer | Zero-based index of this chunk |
| chunk_count | integer | Total chunks in this response |
| presences? | array[presence object] | Visible presences, when the request set presences |
| nonce? | string | The request's nonce, when it asked for one guild |
GUILD_MEMBER_LIST_UPDATE
Section titled “GUILD_MEMBER_LIST_UPDATE”A member list the session subscribed to with Lazy Request changed, and the event resends the subscribed ranges.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the list belongs to |
| id | string | List identifier, which is the channel ID |
| channel_id? | snowflake | Channel the list is scoped to |
| member_count | integer | Total members in the list |
| online_count | integer | Online members in the list |
| groups | array[member list group object] | Group headers in list order |
| ops | array[member list operation object] | Operations to apply |
Member list group object
Section titled “Member list group object”| Field | Type | Description |
|---|---|---|
| id | string | A hoisted role ID, online or offline |
| count | integer | Members in the group |
Hoisted roles come first, then online, then offline. Empty groups are left out, and so is the offline group and its members when it has more than 1,000 members.
Member list operation object
Section titled “Member list operation object”| Field | Type | Description |
|---|---|---|
| op | string | Operation kind, always SYNC |
| range | array[integer] | Inclusive [start, end] range this operation replaces |
| items | array[member list item object] | Replacement items for the range |
Member list item object
Section titled “Member list item object”Each item has exactly one of these fields.
| Field | Type | Description |
|---|---|---|
| group? | member list group object | A group header in one list position |
| member?1 | guild member object | A member of the list |
1 With a presence field, which is {"status": "offline", "mobile": false, "afk": false} when the member is not visibly online
GUILD_AUDIT_LOG_ENTRY_CREATE
Section titled “GUILD_AUDIT_LOG_ENTRY_CREATE”An audit log entry was written. Every session with VIEW_AUDIT_LOG gets it. The payload is the audit log entry with guild_id added and any ip entry left out of changes. Treat a missing options or changes as empty.
GUILD_BAN_ADD
Section titled “GUILD_BAN_ADD”A user was banned.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the ban was created in |
| user | object | The banned user, with id only |
GUILD_BAN_REMOVE
Section titled “GUILD_BAN_REMOVE”A ban was removed.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the ban was removed from |
| user | object | The unbanned user, with id only |
PRESENCE_UPDATE
Section titled “PRESENCE_UPDATE”A visible presence changed. The payload is a presence object. You get presences for friends, group direct message recipients and the guild members you name in a Lazy Request, as Presence subscriptions describes.
Presence object
Section titled “Presence object”| Field | Type | Description |
|---|---|---|
| user | partial user object | The user the presence belongs to |
| status | string | online, idle, dnd or offline |
| mobile | boolean | Whether the user's active status comes from a mobile session |
| afk | boolean | Whether every one of the user's sessions is away, always false when mobile is true |
| custom_status | ?custom status object | The user's custom status, null when offline |
| guild_id? | snowflake | Guild the presence came through |
status is the first of dnd, online and idle that any live session has. An invisible user, or one with no live session, shows as offline. A session that loses its connection stops counting after 5 seconds.
Custom status object
Section titled “Custom status object”| Field | Type | Description |
|---|---|---|
| text | ?string | Custom status text |
| expires_at | ?ISO8601 timestamp | When the custom status expires |
| emoji_id | ?snowflake | Custom emoji ID |
| emoji_name | ?string | Unicode emoji, or the custom emoji's name |
| emoji_animated | boolean | Whether the custom emoji is animated |
PRESENCE_UPDATE_BULK
Section titled “PRESENCE_UPDATE_BULK”The online presences of a guild that was unavailable, sent right after the Guild Create that restores it.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the presences belong to |
| presences | array[presence object] | Up to 500 presences, split across several events when there are more |
PASSIVE_UPDATES
Section titled “PASSIVE_UPDATES”Fluxer sends this every 30 seconds, when something changed, for a guild with more than 250 members where the session is passive.
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the update is about |
| channels | map[snowflake, snowflake] | New last_message_id for each changed channel the session can view |
| voice_states? | array[voice state object] | Changed voice states, with a null channel_id for someone who left |
Messages and reactions
Section titled “Messages and reactions”MESSAGE_CREATE
Section titled “MESSAGE_CREATE”A message was created. The payload is the message object with these fields added.
| Field | Type | Description |
|---|---|---|
| channel_type | integer | Channel type of the message's channel |
| nicks? | map[snowflake, string] | Group direct message nicknames, when the group has any |
| mention_here? | boolean | true when the message has a here mention |
| guild_id? | snowflake | Guild the channel belongs to |
| member? | guild member object | The author's member object without user, in a guild channel |
A published message also arrives as Message Create in each following channel, with the IS_CROSSPOST flag.
MESSAGE_UPDATE
Section titled “MESSAGE_UPDATE”A message changed. The payload is the full message object and, in a guild channel, guild_id and member as in Message Create. Sessions need READ_MESSAGE_HISTORY unless the message is newer than the guild's message history cutoff.
MESSAGE_DELETE
Section titled “MESSAGE_DELETE”A message was deleted.
| Field | Type | Description |
|---|---|---|
| id | snowflake | The deleted message |
| channel_id | snowflake | Channel the message was in |
| content?1 | ?string | The message's content before it was deleted |
| author_id?1 | snowflake | Account that wrote the message |
| guild_id? | snowflake | Guild the channel belongs to |
| member? | guild member object | The author's member object without user, when the author is still a member |
1 Absent when an instance admin or Fluxer itself deleted the message
MESSAGE_DELETE_BULK
Section titled “MESSAGE_DELETE_BULK”Several messages in one channel were deleted at once.
| Field | Type | Description |
|---|---|---|
| ids | array[snowflake] | The deleted messages |
| channel_id | snowflake | Channel the messages were in |
| guild_id? | snowflake | Guild the channel belongs to |
MESSAGE_ACK
Section titled “MESSAGE_ACK”The current user's read state moved forward in a channel, usually from another of their sessions.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel whose read state moved |
| message_id | snowflake | Message the read state now points at |
| mention_count | integer | Remaining mention count for the channel |
| manual? | boolean | Whether the user marked it read by hand |
| version? | string | Read state version as a decimal string |
| flags? | integer | Read state flags, for a thread, forum or media channel |
MESSAGE_REACTION_ADD
Section titled “MESSAGE_REACTION_ADD”A user reacted to a message.
| Field | Type | Description |
|---|---|---|
| user_id | snowflake | User that reacted |
| channel_id | snowflake | Channel the message is in |
| message_id | snowflake | Message that was reacted to |
| emoji | reaction emoji object | The emoji |
| guild_id? | snowflake | Guild the channel belongs to |
| member? | guild member object | The reacting user's member object, in a guild channel |
| session_id? | string | The session that made the request, in a private channel |
Reaction emoji object
Section titled “Reaction emoji object”| Field | Type | Description |
|---|---|---|
| name | string | Unicode emoji, or the custom emoji's name |
| id? | snowflake | Custom emoji ID, absent for a Unicode emoji |
| animated?1 | boolean | Whether the custom emoji is animated |
1 Only on the first reaction with that emoji on the message. An absent animated does not mean false.
MESSAGE_REACTION_ADD_MANY
Section titled “MESSAGE_REACTION_ADD_MANY”Reactions in private channels, grouped over 650 ms, for a session with the DEBOUNCE_MESSAGE_REACTIONS session flag. Each window keeps only the latest 512 reactions and drops older ones. Each event covers one message. A window with a single reaction sends Message Reaction Add.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the message is in |
| message_id | snowflake | Message that was reacted to |
| guild_id? | snowflake | Guild the channel belongs to |
| reactions | array[reaction addition object] | The reactions, oldest first |
Reaction addition object
Section titled “Reaction addition object”| Field | Type | Description |
|---|---|---|
| user_id | snowflake | User that reacted |
| emoji | reaction emoji object | The emoji |
| member? | guild member object | The reacting user's member object, in a guild channel |
MESSAGE_REACTION_REMOVE
Section titled “MESSAGE_REACTION_REMOVE”A user's reaction was removed.
| Field | Type | Description |
|---|---|---|
| user_id | snowflake | User whose reaction was removed |
| channel_id | snowflake | Channel the message is in |
| message_id | snowflake | Message the reaction was on |
| emoji | reaction emoji object | The emoji |
| guild_id? | snowflake | Guild the channel belongs to |
| member? | guild member object | The user's member object, in a guild channel |
| session_id? | string | The session that made the request, in a private channel |
MESSAGE_REACTION_REMOVE_ALL
Section titled “MESSAGE_REACTION_REMOVE_ALL”Every reaction on a message was removed.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the message is in |
| message_id | snowflake | Message whose reactions were cleared |
| guild_id? | snowflake | Guild the channel belongs to |
MESSAGE_REACTION_REMOVE_EMOJI
Section titled “MESSAGE_REACTION_REMOVE_EMOJI”Every reaction with one emoji was removed from a message.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the message is in |
| message_id | snowflake | Message the reactions were on |
| emoji | reaction emoji object | The emoji whose reactions were removed |
| guild_id? | snowflake | Guild the channel belongs to |
TYPING_START
Section titled “TYPING_START”A user started typing. Typing is decided separately explains which sessions get it.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the user is typing in |
| user_id | snowflake | User that started typing |
| timestamp | integer | Unix seconds when typing started |
| guild_id? | snowflake | Guild the channel belongs to |
| member? | guild member object | The typing user's member object, in a guild channel |
CHANNEL_PINS_UPDATE
Section titled “CHANNEL_PINS_UPDATE”A channel's most recent pin time changed.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel whose pins changed |
| last_pin_timestamp | ?ISO8601 timestamp | Time of the most recent pin, null when nothing is pinned |
| guild_id? | snowflake | Guild the channel belongs to |
CHANNEL_PINS_ACK
Section titled “CHANNEL_PINS_ACK”The current user marked a channel's pins as seen.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel whose pins were acknowledged |
| timestamp | ISO8601 timestamp | Time the acknowledgement recorded |
Voice and calls
Section titled “Voice and calls”VOICE_STATE_UPDATE
Section titled “VOICE_STATE_UPDATE”A participant's voice state changed. The payload is a voice state object, and a null channel_id means they left.
Voice state object
Section titled “Voice state object”| Field | Type | Description |
|---|---|---|
| guild_id | ?snowflake | Guild the voice channel belongs to, null in a call |
| channel_id | ?snowflake | Voice channel, null when the participant left |
| user_id | ?snowflake | Participant |
| connection_id | ?string | Voice connection ID |
| session_id | ?string | Gateway session that owns the connection |
| member | ?guild member object | The participant's member object, null in a call |
| mute | boolean | Server mute |
| deaf | boolean | Server deafen |
| self_mute | boolean | Local microphone mute |
| self_deaf | boolean | Local output deafen |
| self_video | boolean | Whether the participant sends camera video |
| self_stream1 | boolean | Whether the connection is sharing its screen |
| is_mobile | boolean | Whether the participant is on a mobile app |
| suppress | boolean | Whether the participant is suppressed |
| viewer_stream_keys | array[string] | Streams this connection is watching |
| e2ee_capable | boolean | Whether the participant's app supports end-to-end encrypted voice |
| p2p | boolean | Whether this connection sends media peer-to-peer |
| version | integer | Version of this participant's voice state, which only goes up |
1 Always false in a guild voice channel when the participant lacks STREAM
VOICE_SERVER_UPDATE
Section titled “VOICE_SERVER_UPDATE”The session got a voice grant, sent only to the session that asked. A LiveKit grant has token and endpoint. A peer-to-peer grant has p2p: true and ice_servers, and you follow Peer-to-peer voice. Voice has the rest.
| Field | Type | Description |
|---|---|---|
| token?1 | string | LiveKit access token |
| endpoint?1 | string | LiveKit ws:// or wss:// URL |
| p2p?2 | boolean | Always true when present |
| ice_servers?2 | array[ICE server object] | STUN servers for the peer connections, empty when the instance has none |
| connection_id | string | The voice connection the grant is for |
| channel_id | snowflake | The channel the grant is for |
| guild_id? | snowflake | The guild the channel belongs to, absent for a call |
| e2ee_key?3 | string | Key for the channel's end-to-end encryption |
1 On a LiveKit grant
2 On a peer-to-peer grant
3 On a LiveKit grant for an end-to-end encrypted channel
A new grant comes when the connection opens, moves to another channel or changes region. A LiveKit grant for a connection that had a peer-to-peer grant means the call switched to LiveKit. Close your peer connections and connect with the new grant.
ICE server object
Section titled “ICE server object”| Field | Type | Description |
|---|---|---|
| urls | array[string] | The stun: URLs of one server |
Fluxer never gives out a TURN server, and peers that can't connect to each other directly can't call.
Peer-to-peer voice
Section titled “Peer-to-peer voice”A voice channel or call is peer-to-peer when every voice state in it has p2p: true. Each pair of connections then has its own WebRTC peer connection and no media goes through LiveKit. Peers exchange session descriptions and ICE candidates with the Voice Signal command.
Fluxer decides each join from the channel's state and the p2p value in the Voice State Update command. A bot always counts as not sending p2p: true.
| Channel or call | The command sent p2p: true | Any other p2p value |
|---|---|---|
| Peer-to-peer below the participant cap | Peer-to-peer join1 | Refused with VOICE_P2P_CONSENT_REQUIRED |
| Peer-to-peer at the participant cap | Refused with VOICE_CHANNEL_FULL | Refused with VOICE_P2P_CONSENT_REQUIRED |
| Empty | Peer-to-peer join, or a LiveKit join when Fluxer declines | LiveKit join |
| Every other state | LiveKit join | LiveKit join |
1 Refused with VOICE_P2P_UNAVAILABLE when Fluxer declines peer-to-peer for this join
A refusal arrives as a Gateway Error and changes nothing. On VOICE_P2P_CONSENT_REQUIRED, ask the user and send the join again with p2p: true if they agree. The participant cap is max_participants from the peer-to-peer voice configuration, between 2 and 4.
Fluxer never switches a call to LiveKit on its own. Only a participant sending p2p: false for its own connection, or a region change through Modify call region or Modify channel, switches it. The call stays on LiveKit until it empties. A guild voice channel with rtc_p2p set never switches.
VOICE_SIGNAL
Section titled “VOICE_SIGNAL”Another connection in a peer-to-peer call sent this session a signaling message with the Voice Signal command. Only the session that owns the target connection receives it. Ignore a signal whose from is no longer in your roster.
| Field | Type | Description |
|---|---|---|
| guild_id? | snowflake | The guild the channel belongs to, absent for a call |
| channel_id | snowflake | The voice channel or call channel |
| from | string | The connection_id of the sender |
| user_id | snowflake | The user who owns the sending connection |
| data | object | The signaling message exactly as the sender sent it |
{ "guild_id": "1189375284394692608", "channel_id": "1189375284394692610", "from": "9a41d07c5be2f318", "user_id": "1189375284394692700", "data": { "type": "answer", "sdp": "v=0..." }}ENTRANCE_SOUND_PLAY
Section titled “ENTRANCE_SOUND_PLAY”A participant played their entrance sound in the voice channel they are in. Everyone else with a voice state in the channel receives it.
| Field | Type | Description |
|---|---|---|
| user_id | snowflake | Participant whose sound plays |
| channel_id | snowflake | Voice channel |
| guild_id | ?snowflake | Guild the channel belongs to, null for a call |
| sound_id | snowflake | Entrance sound |
| hash | string | Content hash of the sound file |
| url | string | URL to fetch the sound from |
| duration_ms | integer | Sound duration in milliseconds |
| content_type | string | MIME type of the sound file |
CALL_CREATE
Section titled “CALL_CREATE”A call started in a private channel, or the session learned of an active one after Ready or a lost connection. Every recipient of the channel receives it, and the same goes for Call Update and Call Delete.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the call is in |
| message_id | snowflake | Call message that started the call |
| region | ?string | Voice region of the call, null until one is chosen |
| ringing | array[snowflake] | Recipients being rung |
| voice_states | array[voice state object] | Participants |
| recipients?1 | array[snowflake] | Every recipient of the channel |
| created_at?1 | integer | Unix milliseconds when the call started |
1 Only after Ready or a lost connection
CALL_UPDATE
Section titled “CALL_UPDATE”Who is ringing, who is in the call or the call's region changed. The payload has the same fields as Call Create without recipients and created_at.
CALL_DELETE
Section titled “CALL_DELETE”A call ended or became unavailable. Keep an unavailable call until a new Call Create arrives.
| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | Channel the call was in |
| unavailable? | boolean | True when the call became unavailable, absent when it ended |
Count response events
Section titled “Count response events”GUILD_COUNTS_UPDATE
Section titled “GUILD_COUNTS_UPDATE”The answer to Request Guild Counts. A guild that isn't connected or didn't answer in time has no entry.
| Field | Type | Description |
|---|---|---|
| counts | array[guild count entry object] | One entry per guild |
| nonce? | string | The request's nonce |
Guild count entry object
Section titled “Guild count entry object”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the counts are for |
| member_count | integer | Total members |
| online_count | integer | Online members who share a channel you can view, or all of them for ADMINISTRATOR |
CHANNEL_MEMBER_COUNTS_UPDATE
Section titled “CHANNEL_MEMBER_COUNTS_UPDATE”The answer to Request Channel Member Counts. You only get an entry for a channel where you have VIEW_CHANNEL_MEMBERS.
| Field | Type | Description |
|---|---|---|
| counts | array[channel count entry object] | One entry per channel |
| nonce? | string | The request's nonce |
Channel count entry object
Section titled “Channel count entry object”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | Guild the channel belongs to |
| channel_id | snowflake | Channel the counts are for |
| member_count | integer | Members who can view the channel |
| online_count | integer | Online members who can view the channel |