Gateways are Discord's form of real-time communication over secure websockets. Clients will receive events and data over the gateway they are connected to and send data over the REST API. For information about connecting to a gateway see the Connecting section.
Returns an object with a single valid WSS URL. Clients should cache this value, and only call this endpoint to retrieve a new URL if they are unable to establish a Gateway connection to the cached URL.
{
"url": "wss://gateway.discord.gg/"
}
Out of Services versions are versions whose subset of changes compared to the most recent version have been completely removed from the Gateway. When connecting with these versions, the gateway may reject your connection entirely.
Version | Out of Service |
---|---|
5 | no |
4 | no |
Field | Type | Description | Present |
---|---|---|---|
op | integer | opcode for the payload | Always |
d | mixed (object, integer) | event data | Always |
s | integer | sequence number, used for resuming sessions and heartbeats | Only for OP 0 |
t | string | the event name for this payload | Only for OP 0 |
Code | Name | Description |
---|---|---|
0 | Dispatch | dispatches an event |
1 | Heartbeat | used for ping checking |
2 | Identify | used for client handshake |
3 | Status Update | used to update the client status |
4 | Voice State Update | used to join/move/leave voice channels |
5 | Voice Server Ping | used for voice ping checking |
6 | Resume | used to resume a closed connection |
7 | Reconnect | used to tell clients to reconnect to the gateway |
8 | Request Guild Members | used to request guild members |
9 | Invalid Session | used to notify client they have an invalid session id |
10 | Hello | sent immediately after connecting, contains heartbeat and server debug information |
11 | Heartback ACK | sent immediately following a client heartbeat that was received |
Used by the gateway to notify the client of events.
{
"op": 0,
"d": {},
"s": 42,
"t": "GATEWAY_EVENT_NAME"
}
Used to maintain an active gateway connection. Must be sent every heartbeat_interval
milliseconds after the ready payload is received. Note that this interval already has room for error, and that client implementations do not need to send a heartbeat faster than what's specified. The inner d
key must be set to the last seq (s
) received by the client. If none has yet been received you should send null
(you cannot send a heartbeat before authenticating, however).
info It is worth noting that in the event of a service outage where you stay connected to the gateway, you should continue to heartbeat and receive ACKs. The gateway will eventually respond and issue a session once it is able to.
{
"op": 1,
"d": 251
}
Used for the client to maintain an active gateway connection. Sent by the server after receiving a Gateway Heartbeat
{
"op": 11
}
Sent on connection to the websocket. Defines the heartbeat interval that the client should heartbeat to.
Field | Type | Description |
---|---|---|
heartbeat_interval | integer | the interval (in milliseconds) the client should heartbeat with |
_trace | array of strings | used for debugging, array of servers connected to |
{
"heartbeat_interval": 45,
"_trace": ["discord-gateway-prd-1-99"]
}
Used to trigger the initial handshake with the gateway.
Field | Type | Description |
---|---|---|
token | string | authentication token |
properties | object | connection properties |
compress | bool | whether this connection supports compression of the initial ready packet |
large_threshold | integer | value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list |
shard | array of two integers (shard_id, num_shards) | used for Guild Sharding |
{
"token": "my_token",
"properties": {
"$os": "linux",
"$browser": "my_library_name",
"$device": "my_library_name",
"$referrer": "",
"$referring_domain": ""
},
"compress": true,
"large_threshold": 250,
"shard": [1, 10]
}
Used to tell clients to reconnect to the gateway. Clients should immediately reconnect, and use the resume payload on the gateway.
Used to request offline members for a guild. When initially connecting, the gateway will only send offline members if a guild has less than the large_threshold
members (value in the Gateway Identify). If a client wishes to receive all members, they need to explicitly request them. The server will send a Guild Members Chunk event in response.
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild to get offline members for |
query | string | string that username starts with, or an empty string to return all members |
limit | integer | maximum number of members to send or 0 to request all members matched |
{
"guild_id": "41771983444115456",
"query": "",
"limit": 0
}
Used to replay missed events when a disconnected client resumes.
Field | Type | Description |
---|---|---|
token | string | session token |
session_id | string | session id |
seq | integer | last sequence number received |
{
"token": "randomstring",
"session_id": "evenmorerandomstring",
"seq": 1337
}
Sent by the client to indicate a presence or status update.
Field | Type | Description |
---|---|---|
idle_since | ?integer | unix time (in milliseconds) of when the client went idle, or null if the client is not idle |
game | ?object | either null, or an object with one key "name", representing the name of the game being played |
{
"idle_since": 91879201,
"game": {
"name": "Writing Docs FTW"
}
}
Sent when a client wants to join, move, or disconnect from a voice channel.
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild |
channel_id | ?snowflake | id of the voice channel client wants to join (null if disconnecting) |
self_mute | bool | is the client muted |
self_deaf | bool | is the client deafened |
{
"guild_id": "41771983423143937",
"channel_id": "127121515262115840",
"self_mute": false,
"self_deaf": false
}
The first step to establishing a gateway connection is to request a gateway URL through the Get Gateway API endpoint (if the client does not already have one cached). Using the "url" field from the response you can then create a new secure websocket connection that will be used for the duration of your gateway session. Once connected, the client will immediately receive an OP 10 Hello payload with the connection heartbeat interval. At this point the client should start sending OP 1 heartbeat payloads every heartbeat_interval
seconds. Next, the client sends an OP 2 Identify or OP 6 Resume payload. If your token is correct, the gateway will respond with a Ready payload.
Field | Type | Description |
---|---|---|
v | integer | Gateway Version to use |
encoding | string | 'json' or 'etf' |
When clients lose their connection to the gateway and are able to reconnect in a short period of time after, they can utilize a Gateway feature called "client resuming". Once reconnected to the gateway socket the client should send a Gateway Resume payload to the server. If successful, the gateway will respond by replaying all missed events to the client. Otherwise, the gateway will respond with an OP 9 (invalid session), in which case the client should send an OP 2 Identify payload to start a new connection. It is recommended that all Discord clients implement resume logic. The gateway can and will disconnect your websocket connection as it pleases without any warning. Implementing this feature will allow your client to reconnect seamlessly. Resuming is only supported when the amount of guilds in a given gateway connection is under 2,500. In order to resume as your bot grows, it's recommended that you shard your gateway connection to reduce the number of guilds per gateway connection.
If the gateway ever issues a disconnect to your client it will provide a close event code that you can use to properly handle the disconnection.
Code | Description | Explanation |
---|---|---|
4000 | unknown error | We're not sure what went wrong. Try reconnecting? |
4001 | unknown opcode | You sent an invalid Gateway OP Code. Don't do that! |
4002 | decode error | You sent an invalid payload to us. Don't do that! |
4003 | not authenticated | You sent us a payload prior to identifying. |
4004 | authentication failed | The account token sent with your identify payload is incorrect. |
4005 | already authenticated | You sent more than one identify payload. Don't do that! |
4007 | invalid seq | The sequence sent when resuming the session was invalid. Reconnect and start a new session. |
4008 | rate limited | Woah nelly! You're sending payloads to us too quickly. Slow it down! |
4009 | session timeout | Your session timed out. Reconnect and start a new one. |
4010 | invalid shard | You sent us an invalid shard when identifying. |
When initially creating and handshaking connections to the Gateway, a user can chose whether they wish to communicate over plain-text JSON, or binary ETF. Payloads to the gateway are limited to a maximum of 4096 bytes sent, going over this will cause a connection termination with error code 4002. Additionally, when using ETF, the client must not send compressed messages to the server.
Unlike the HTTP API, the Gateway does not provide a method for forced back-off or cooldown but instead implement a hard limit on the number of messages sent over a period of time. Currently clients are allowed 120 events every 60 seconds, meaning you can send on average at a rate of up to 2 events per second. Clients who surpass this limit are immediately disconnected from the Gateway, and similarly to the HTTP API, repeat offenders will have their API access revoked. Clients are limited to one gateway connection per 5 seconds, if you hit this limit the Gateway will delay your connection until the cooldown has timed out.
warn Clients may only update their game status 5 times per minute.
Users who implement the Gateway API should keep in mind that Discord expects clients to track state locally and will only provide events for objects that are created/updated/deleted. A good example of state tracking is user status, when initially connecting to the gateway, the client receives information regarding the online status of members. However to keep this state updated a user must receive and track Presence Updates. Generally clients should try to cache and track as much information locally to avoid excess API calls.
When connecting to the gateway as a bot user, guilds that the bot is a part of start out as unavailable. Unavailable simply means that the gateway is either connecting, is unable to connect to a guild, or has disconnected from a guild. Don't fret however! When a guild goes unavailable the gateway will automatically attempt to reconnect on your behalf. As far as a client is concerned there is no distinction between a truly unavailable guild (meaning that the node that the guild is running on is unavailable) or a guild that the client is trying to connect to. As such, guilds only exist in two states: available or unavailable.
As bots grow and are added to an increasing number of guilds, some developers may find it necessary to break or split portions of their bots operations into separate logical processes. As such, Discord gateways implement a method of user-controlled guild-sharding which allows for splitting events across a number of gateway connections. Guild sharding is entirely user controlled, and requires no state-sharing between separate connections to operate.
To enable sharding on a connection, the user should send the shard
array in the identify payload. The first item in this array should be the zero-based integer value of the current shard, while the second represents the total number of shards. DMs will only be sent to shard 0. To calculate what events will be sent to what shard, the following formula can be used:
(guild_id >> 22) % num_shards == shard_id
As an example, if you wanted to split the connection between three shards, you'd use the following values for shard
for each connection: [0, 3]
, [1, 3]
, and [2, 3]
. Note that only the first shard ([0, 3]
) would receive DMs.
Packets sent from the client to the Gateway API are encapsulated within a gateway payload object and must have the proper OP code and data object set. The payload object can then be serialized in the format of choice, and sent over the websocket.
Receiving payloads with the Gateway API is slightly more complex than sending. When using the JSON encoding with compression enabled, the Gateway has the option of sending payloads as compressed JSON binaries using zlib, meaning your library must detect and decompress these payloads before attempting to parse them. The gateway does not implement a shared compression context between messages sent.
Event names are in standard constant form, fully upper-cased and replacing all spaces with underscores. For instance, Channel Create would be CHANNEL_CREATE
and Voice State Update would be VOICE_STATE_UPDATE
.
The ready event is dispatched when a client has completed the initial handshake with the gateway (for new sessions). The ready event can be the largest and most complex event the gateway will send, as it contains all the state required for a client to begin interacting with the rest of the platform.
Field | Type | Description |
---|---|---|
v | integer | gateway protocol version |
user | object | user object (with email information) |
private_channels | array | array of DM channel objects |
guilds | array | array of Unavailable Guild objects |
session_id | string | used for resuming connections |
presences | array | list of friends' presences (not applicable to bots) |
relationships | array | list of friends (not applicable to bots) |
_trace | array of strings | used for debugging, array of servers connected to |
The resumed event is dispatched when a client has sent a resume payload to the gateway (for resuming existing sessions).
Field | Type | Description |
---|---|---|
_trace | array of strings | used for debugging, array of servers connected to |
Sent when a new channel is created, relevant to the current user. The inner payload is a DM or Guild channel object.
Sent when a channel is updated. The inner payload is a guild channel object.
Sent when a channel relevant to the current user is deleted. The inner payload is a DM or Guild channel object.
This event can be sent in three different scenarios:
- When a user is initially connecting, to lazily load and backfill information for all unavailable guilds sent in the ready event.
- When a Guild becomes available again to the client.
- When the current user joins a new Guild.
The inner payload is a guild object, with an extra presences key containing an array of simple presence objects. The simple presence objects each have the same fields as a Presence Update event without a roles or guild_id key.
Sent when a guild is updated. The inner payload is a guild object.
Sent when a guild becomes unavailable during a guild outage, or when the user leaves or is removed from a guild. See GUILD_CREATE for more information about how to handle this event.
Field | Type | Description |
---|---|---|
id | snowflake | id of the guild |
unavailable | bool | whether the guild is unavailable, should always be true. if not set, this signifies that the user was removed from the guild |
Sent when a user is banned from a guild. The inner payload is a user object, with an extra guild_id key.
Sent when a user is unbanned from a guild. The inner payload is a user object, with an extra guild_id key.
Sent when a guilds emojis have been updated.
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild |
emojis | array | array of emojis |
Sent when a guild integration is updated.
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild whose integrations where updated |
Sent when a new user joins a guild. The inner payload is a guild member object with these extra fields:
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild |
Sent when a user is removed from a guild (leave/kick/ban).
Field | Type | Description |
---|---|---|
guild_id | snowflake | the id of the guild |
user | a user object | the user who was removed |
Sent when a guild member is updated.
Field | Type | Description |
---|---|---|
guild_id | snowflake | the id of the guild |
roles | array of role objects | user roles |
user | a user object | the user |
Sent in response to Gateway Request Guild Members.
Field | Type | Description |
---|---|---|
guild_id | snowflake | the id of the guild |
members | array of guild members | set of guild members |
Sent when a guild role is created.
Field | Type | Description |
---|---|---|
guild_id | snowflake | the id of the guild |
role | a role object | the role created |
Sent when a guild role is updated.
Field | Type | Description |
---|---|---|
guild_id | snowflake | the id of the guild |
role | a role object | the role created |
Sent when a guild role is deleted.
Field | Type | Description |
---|---|---|
guild_id | snowflake | id of the guild |
role_id | snowflake | id of the role |
Sent when a message is created. The inner payload is a message object.
Sent when a message is updated. The inner payload is a message object.
warn Unlike creates, message updates may contain only a subset of the full message object payload (but will always contain an id and channel_id).
Sent when a message is deleted.
Field | Type | Description |
---|---|---|
id | snowflake | the id of the message |
channel_id | snowflake | the id of the channel |
Sent when multiple messages are deleted at once.
Field | Type | Description |
---|---|---|
ids | array of snowflakes | the ids of the messages |
channel_id | snowflake | the id of the channel |
A user's presence is their current state on a guild. This event is sent when a user's presence is updated for a guild.
warn The user object can be partial. The only field that it must contain is the "id" - every other field is optional, and won't be sent if they aren't updated.
Field | Type | Description |
---|---|---|
user | user object | the user presence is being updated for |
roles | array of snowflakes | roles this user is in |
game | object | null, or an object containing one key of "name" |
nick | string | nickname of the user in the guild |
guild_id | snowflake | id of the guild |
status | string | either "idle", "online" or "offline" |
Sent when a user starts typing in a channel.
Field | Type | Description |
---|---|---|
channel_id | snowflake | id of the channel |
user_id | snowflake | id of the user |
timestamp | timestamp | when the user started typing |
Sent when the current user updates their settings. Inner payload is a user settings object.
Sent when properties about the user change. Inner payload is a user object.
Sent when someone joins/leaves/moves voice channels. Inner payload is a voice state object.
{
"user_id": "104694319306248192",
"session_id": "my_session_id"
}
Sent when a guild's voice server is updated. This is sent when initially connecting to voice, and when the current voice instance fails over to a new server.
Field | Type | Description |
---|---|---|
token | string | voice connection token |
guild_id | snowflake | the guild this voice server update is for |
endpoint | string | the voice server host |
{
"token": "my_token",
"guild_id": "41771983423143937",
"endpoint": "smart.loyal.discord.gg"
}