Visão geral do Gateway
O Gateway principal é um WebSocket persistente. Ele envia eventos de conta e de servidores e aceita um conjunto reduzido e delimitado de comandos de cliente. Todas as outras operações de leitura ou mutação são feitas através da API HTTP.
Conectando
Seção intitulada “Conectando”O cliente abre o socket, aguarda o Hello, envia Identify e mantém heartbeats periódicos durante toda a vida da conexão.
- Leia
endpoints.gatewaya partir do documento de descoberta da instância e abra um WebSocket para ele com?v=1&encoding=json. - Leia o Opcode 10 Hello e obtenha o
heartbeat_intervalinformado. - Envie o Opcode 2 Identify com o token e as
properties. - Leia o evento Ready e guarde seu
session_idpara uma futura Retomada. - Envie o Opcode 1 Heartbeat com o último número de sequência de Dispatch a cada intervalo de
heartbeat_intervalmilissegundos.
{ "op": 2, "d": { "token": "flx_ZDb1GURItsMuYl1zvrgxv2qLBxyNmgNSEaWT", "properties": { "os": "Linux", "browser": "Decoding Client", "device": "desktop" } }}Apenas token e properties são obrigatórios. Envie o token bruto de usuário ou bot sem prefixos de autenticação HTTP. Consulte Identify para os campos opcionais. As atualizações de conta e de servidores chegam como Dispatches, com o nome do evento em t e seus dados em d.
Versão do protocolo
Seção intitulada “Versão do protocolo”A versão 1 do Gateway é a única suportada. O parâmetro de conexão v=1 a seleciona. O Gateway encerra a conexão com o código 4012 e motivo Invalid API version para qualquer outro valor ou quando o parâmetro for omitido, antes mesmo de enviar o Hello.
Descobrindo o endpoint
Seção intitulada “Descobrindo o endpoint”Leia endpoints.gateway a partir do documento de descoberta da instância. Bots podem chamar alternativamente GET /v1/gateway/bot, que retorna a mesma URL de WebSocket acompanhada da contagem recomendada de shards e de um objeto com os limites de início de sessão. Essa rota rejeita qualquer credencial fora do formato de token de bot com 401 INVALID_AUTH_TOKEN.
Parâmetros de conexão
Seção intitulada “Parâmetros de conexão”Acrescente os parâmetros de conexão à URL descoberta.
| Campo | Tipo | Descrição |
|---|---|---|
| v | integer | Versão do protocolo Gateway, que é 1 |
| encoding?1 | string | Codificação do payload |
| compress?2 | string | Fluxo de compressão, aceitando zstd-stream ou none (padrão: sem compressão) |
| stream?3 | string | Flag que habilita o fluxo de compressão, aceitando 1 ou true |
1 Apenas json está implementado. Todo valor, incluindo quando omitido, seleciona JSON
2 Qualquer outro valor seleciona sem compressão
3 compress=zstd-stream seleciona compressão apenas quando stream também for 1 ou true. Sem a flag, a conexão não usa compressão
Parâmetros desconhecidos são ignorados. Um valor não reconhecido de compress ou stream seleciona sem compressão e a conexão permanece aberta. O cliente DEVE identificar se a conexão é comprimida a partir do tipo de frame recebido. Em uma conexão zstd-stream, todos os frames enviados pelo servidor são frames binários.
O cliente de referência conecta com ?v=1&encoding=json&compress=zstd-stream&stream=1.
Payload do Gateway
Seção intitulada “Payload do Gateway”Toda mensagem lógica utiliza o payload padrão do Gateway.
| Campo | Tipo | Descrição |
|---|---|---|
| op | integer | Opcode do Gateway |
| d?1 | any | Payload do opcode, obrigatório em todo payload enviado de cliente para servidor e variável de acordo com o opcode de servidor para cliente |
| s? | integer | Número de sequência não negativo da sessão, presente apenas em Dispatch |
| t? | string | Nome do evento, presente apenas em Dispatch |
1 Heartbeat ACK e Reconnect não possuem campo d, e Invalid Session envia o booleano false
Um payload decodificado que não seja um objeto JSON encerra a conexão com 4002 e motivo Decode failed. Um objeto sem op fecha com 4002 e motivo Invalid payload. Um objeto com op, mas sem d, fecha com 4001 e motivo Unknown opcode, exceto para Identify e Resume, que fecham com 4005.
Um Dispatch é um payload de evento enviado do servidor para o cliente. Cada Dispatch em tempo real avança a sequência da sessão em um. Uma sessão inicia na sequência 0, de modo que a sequência de Ready é 1.
Um Dispatch reproduzido (replay) mantém sua sequência original, e um lote reproduzido pode conter lacunas, pois Guild Sync, Guild Member List Update e Guild Members Chunk são entregues em tempo real e nunca retidos no buffer. O evento Resumed traz a sequência atual e não a avança. O próximo Dispatch em tempo real após Resumed terá essa sequência mais um. A sequência é local para uma única sessão de Gateway e não tem significado entre sessões ou shards diferentes.
Framing
Seção intitulada “Framing”Uma única mensagem WebSocket de entrada está limitada a 4.096 bytes brutos na conexão, e uma mensagem comprimida de entrada está limitada a mais 4.096 bytes após a descompressão. Uma mensagem que ultrapasse qualquer um desses limites fecha com 4002 e motivo Payload too large. Uma mensagem de entrada que não puder ser descomprimida fecha com 4002 e motivo Decompression failed.
Payloads JSON são objetos em UTF-8. Um payload não comprimido do cliente é enviado em um frame de texto, enquanto um payload comprimido com o fluxo zstd negociado é enviado em um frame binário.
O Gateway não inspeciona o tipo de frame recebido. Ele decodifica todas as mensagens de entrada de acordo com a compressão negociada na conexão, independentemente do tipo de frame. O cliente DEVE enviar todos os payloads na representação negociada. Em uma conexão sem compressão negociada, o payload não é comprimido; em uma conexão zstd-stream, todos os payloads do cliente passam pelo mesmo fluxo contínuo de compressão em ordem.
Representação de inteiros em JSON
Seção intitulada “Representação de inteiros em JSON”Snowflakes são strings decimais. Consulte Snowflakes para o contrato de identificadores. Sequências, contagens, versões e campos de bits (bitfields) são números JSON.
Compressão
Seção intitulada “Compressão”zstd-stream é um fluxo contínuo em ambas as direções. O cliente DEVE alimentar o mesmo descompressor com todos os frames do servidor na ordem de chegada e gerar todos os frames de envio a partir do mesmo compressor.
Uma única mensagem WebSocket contém exatamente um payload do Gateway.
O Hello já é enviado comprimido em conexões que negociaram zstd-stream, de modo que o primeiro frame recebido nessas conexões é um frame binário.
Caso o servidor não consiga carregar a implementação de streaming zstd, a conexão é encerrada com 4002 e motivo Compression failed: zstd-stream ao tentar enviar o primeiro frame.
Máquina de estados de sinalização
Seção intitulada “Máquina de estados de sinalização”Uma conexão transita entre estes estados: Opening, Unauthenticated, Starting, Replaying e Ready. As tabelas abaixo listam os eventos aceitos por cada estado, a ação disparada e o estado de destino. Heartbeat é aceito em todos os estados abertos, e Closed é o estado final para aquele socket.
Opening
Seção intitulada “Opening”| Evento e condição | Ação | Próximo estado |
|---|---|---|
WebSocket aceito. v=1 e capacidade de conexão disponível | Enviar Hello | Unauthenticated |
Versão inválida. v ausente ou diferente de 1 | Fechar com 4012 e motivo Invalid API version | Closed |
| Limite de conexões simultâneas atingido. O IP de origem já possui 256 conexões | Fechar com 4008 e motivo Too many connections | Closed |
Unauthenticated
Seção intitulada “Unauthenticated”| Evento e condição | Ação | Próximo estado |
|---|---|---|
| Identify. Payload de Identify válido e capacidade de Identify disponível | Iniciar criação de sessão | Starting |
| Identify. Gateway em processo de drain, nó em capacidade máxima, início de sessões pausado ou conta fora do rollout de sessão | Reter o payload e tentar novamente em segundo plano | Unauthenticated |
| Identify. Orçamento de Identify do IP de origem esgotado | Descartar o payload sem responder | Unauthenticated |
| Resume. Payload de Resume válido | Localizar a sessão retida indicada por session_id | Starting |
| Comando autenticado. Qualquer comando que não seja Heartbeat, Identify ou Resume | Fechar com 4003 e motivo Not authenticated | Closed |
Starting
Seção intitulada “Starting”| Evento e condição | Ação | Próximo estado |
|---|---|---|
| Criação de sessão bem-sucedida. Identify foi aceito | Enviar Ready | Ready |
| Falha permanente na criação de sessão. Token inválido, shard inválido, sharding obrigatório ou excesso de sessões | Fechar com o código e motivo listados em Hello e criação de sessão | Closed |
| Falha na criação de sessão com erro não classificado pelo Gateway | Fechar com 4000 e motivo Failed to start session | Closed |
| Falha temporária na criação de sessão. Drain, capacidade máxima, falha de RPC, timeout ou conta fora do rollout | Reter o Identify e tentar novamente em segundo plano | Unauthenticated |
| Retomada bem-sucedida. A sessão retida aceitou o número de sequência | Reproduzir Dispatches retidos | Replaying |
A sessão não pode ser retomada. Resume indicou sessão desconhecida/expirada ou seq abaixo do piso de replay | Enviar Invalid Session com d: false | Unauthenticated |
Replaying
Seção intitulada “Replaying”| Evento e condição | Ação | Próximo estado |
|---|---|---|
| Replay concluído. Todos os Dispatches retidos foram enviados | Enviar Resumed | Ready |
| Comando autenticado. A sessão está vinculada | Processar o comando | Replaying |
| Identify. Uma sessão já está vinculada | Fechar com 4005 e motivo Already authenticated | Closed |
| Resume. Payload de Resume válido | Vincular a sessão indicada a este socket no lugar da atual | Starting |
| Evento e condição | Ação | Próximo estado |
|---|---|---|
| Comando autenticado. O comando é válido na sessão | Processar o comando | Ready |
| Identify. Uma sessão já está vinculada | Fechar com 4005 e motivo Already authenticated | Closed |
| Resume. Payload de Resume válido | Vincular a sessão indicada a este socket no lugar da atual | Starting |
Replaying ou Ready
Seção intitulada “Replaying ou Ready”| Evento e condição | Ação | Próximo estado |
|---|---|---|
| O processo da sessão terminou. A sessão foi encerrada enquanto este socket a mantinha | Enviar Invalid Session com d: false | Unauthenticated |
| Drain do Gateway ou transferência de sessão. O nó deixa de atender a sessão | Enviar Reconnect e fechar com 4000 | Closed |
| A sessão foi retomada em outro local. Outro socket vinculou esta sessão via Resume | Enviar Reconnect e fechar com 4000 | Closed |
Qualquer estado aberto
Seção intitulada “Qualquer estado aberto”| Evento e condição | Ação | Próximo estado |
|---|---|---|
Heartbeat. Nenhuma sessão vinculada, ou payload é null, ou a sessão vinculada aceita a sequência | Enviar Heartbeat ACK | Mesmo estado |
| Prazo de Heartbeat expirado. A conexão aguarda confirmação e mais de 45.000 ms se passaram desde o último ACK | Fechar com 4009 e motivo Heartbeat timeout | Closed |
| Frame ou payload inválido. Falha de validação de tamanho, descompressão ou decodificação | Fechar com 4002 e motivo correspondente em Payload do Gateway ou Framing | Closed |
| Transporte encerrado. Uma sessão existe | Reter a sessão por 60.000 ms | Closed |
Um opcode fora do registro oficial e um opcode de servidor enviado por um cliente fecham com 4001 após a sessão estar vinculada e com 4003 enquanto a conexão estiver não autenticada.
Hello e criação de sessão
Seção intitulada “Hello e criação de sessão”O servidor envia o Opcode 10 Hello ao aceitar o WebSocket.
{ "op": 10, "d": { "heartbeat_interval": 41250 }}O intervalo é informado em milissegundos e é mandatório para a conexão.
O Opcode 2 Identify cria uma sessão. Um Identify bem-sucedido envia Ready, cujo campo session_id identifica a sessão retida. O Decoding Chat não publica uma URL de resume separada; a retomada conecta ao mesmo endpoint de Gateway descoberto pelo cliente.
Um token inválido encerra a conexão com 4004 e motivo Invalid token. Uma conta de usuário que já possui 100 sessões ativas fecha com 4008 e motivo Too many sessions (credenciais de bot não são limitadas por esse máximo). Um par de shards malformado fecha com 4010 e motivo Invalid shard. Uma atribuição de shard de bot que alcance mais de 2.500 servidores fecha com 4011 e motivo Sharding required.
Heartbeats
Seção intitulada “Heartbeats”O Opcode 1 é aceito antes e depois da autenticação. Antes de uma sessão existir, seu payload é ignorado e o servidor responde com ACK normalmente. Assim que uma sessão existir, envie o número de sequência do Dispatch processado mais recentemente, ou null antes de receber qualquer Dispatch.
{ "op": 1, "d": 42}O servidor responde com o Opcode 11 Heartbeat ACK, que não contém d. Com uma sessão vinculada, um valor de d que não seja nem null nem um número inteiro encerra a conexão com 4007 e motivo Invalid sequence. Se o Gateway não conseguir confirmar a sequência com a sessão em até 5.000 ms, a conexão fecha com o mesmo código e motivo.
O servidor solicita um heartbeat imediato com Opcode 1 e d: null se 90% do intervalo tiver decorrido desde o último ACK. Responda a essa solicitação com o seu próprio Opcode 1 e continue enviando heartbeats no intervalo normal anunciado. Uma conexão que perca o prazo de heartbeat fecha com 4009 e motivo Heartbeat timeout.
Um heartbeat com número de sequência remove permanentemente do buffer de replay todos os Dispatches retidos com sequência menor ou igual à informada, registrando-a como sequência confirmada. O cliente DEVE enviar a sequência que efetivamente processou, pois um Resume futuro a partir de uma sequência inferior fechará com 4007.
Retomando uma sessão
Seção intitulada “Retomando uma sessão”O Opcode 6 fornece o token original, o session_id obtido no Ready e a última sequência de Dispatch processada.
{ "op": 6, "d": { "token": "...", "session_id": "6f1d0b7c9a2e4f83b5c1d9e7a4f20b13", "seq": 42 }}Uma retomada bem-sucedida reproduz todos os Dispatches retidos com sequência maior que seq em ordem e conclui enviando Resumed.
Todos os campos são obrigatórios. Campo ausente, token ou session_id que não seja string, ou seq que não seja inteiro fecha com 4002 e motivo Invalid resume payload.
O Gateway retém uma sessão desconectada por 60.000 ms. Um seq aceito não pode ser maior que a sequência atual da sessão nem menor que a sequência que a sessão já confirmou anteriormente. Um seq fora desses limites encerra com 4007 e motivo Invalid sequence.
Uma sessão desconhecida ou expirada envia o Opcode 9 com d: false e mantém o socket no estado não autenticado. Um seq dentro dos limites mas abaixo do piso de replay (replay floor) envia o mesmo Opcode 9. O piso de replay é a sequência mais alta que o buffer de replay já descartou. Um token que não seja dono da sessão indicada fecha com 4004 e motivo Invalid token. Uma sessão inalcançável fecha com 4000 e motivo Session unavailable. Nenhuma dessas falhas destrói uma sessão retida separadamente.
Um Resume bem-sucedido substitui o socket da sessão e restaura o status de presença selecionado por último. Uma sessão cujo socket caiu é publicada como offline após 5.000 ms; portanto, uma retomada após esse prazo republica o status restaurado.
Diferente do Identify, o Resume é aceito em todos os estados abertos. Um socket que já tenha uma sessão vinculada ainda processa um Resume e vincula a sessão indicada no lugar da atual. Envie Resume preferencialmente em um socket novo.
Quando a sessão retomada estiver vinculada a um socket diferente, o socket anterior recebe o Opcode 7 Reconnect e encerra com 4000.
Reconnect
Seção intitulada “Reconnect”O Opcode 7 Reconnect solicita que o cliente abra um novo WebSocket. O Gateway o envia quando o nó executa drain da sessão, quando transfere a sessão para outro nó ou para o socket deslocado por um Resume bem-sucedido.
{ "op": 7}O socket atual fecha em seguida com 4000 e motivo Session drain requested; reconnect to continue. Um Resume enviado dentro de 60.000 ms após o fechamento pode recuperar a sessão, respeitando os limites de sequência descritos em Retomando uma sessão.
Invalid Session
Seção intitulada “Invalid Session”O Opcode 9 com d: false indica que a sessão especificada não pode ser retomada. O Gateway o envia quando o Resume referencia uma sessão desconhecida ou expirada, quando indica um seq abaixo do piso de replay ou quando o processo da sessão vinculado a uma conexão ativa termina.
{ "op": 9, "d": false}O socket retorna ao estado não autenticado, permanecendo aberto e apto a enviar Identify novamente. O Decoding Chat nunca envia d: true.
Sharding
Seção intitulada “Sharding”No comando Identify, o cliente PODE fornecer shard como um par [shard_id, shard_count]. shard_id é um inteiro não negativo menor que shard_count, e shard_count varia de 1 até 16.384. Valor omitido ou nulo não aplica sharding. Um par malformado fecha com 4010 e motivo Invalid shard.
Um servidor pertence ao shard ((guild_id >> 22) % shard_count), calculado sobre o valor inteiro da string decimal do snowflake do servidor.
O par seleciona os servidores associados à sessão. No Identify, o Decoding Chat filtra a lista de servidores da conta para aqueles pertencentes ao shard, e a sessão conecta apenas a eles.
Em todas as sessões, o conjunto filtrado compõe também o array guilds no evento Ready. Uma sessão de bot recebe cada um desses servidores inicialmente como indisponível, seguido por um Guild Create ou Guild Delete por servidor. O Ready ecoa o par aceito de volta no campo shard.
Apenas sessões de bot são validadas contra o limite máximo de servidores por shard. Um bot cujo shard pertença a mais de 2.500 servidores fecha com 4011 e motivo Sharding required. Um bot que não forneça o par é validado contra a sua lista completa de servidores. Sessões de usuário são limitadas apenas pelo teto de 100 sessões por usuário, independentemente da contagem de servidores.
O Decoding Chat não possui níveis de bots gigantes (large bot tiers), requisitos de alinhamento de contagem de shards ou filas concorrentes de Identify. GET /v1/gateway/bot retorna uma recomendação fixa.
Ordenação
Seção intitulada “Ordenação”A ordenação de Dispatches é garantida dentro de uma mesma sessão de Gateway. Não há ordenação global entre shards diferentes, respostas HTTP ou operações do Proxy de mídia.
Guild Create e Guild Sync enviam a listagem completa de cargos, canais, emojis, figurinhas e estados de voz para o servidor indicado, e o cliente substitui suas listas locais por elas. Todos os demais Dispatches para aquele servidor alteram incrementalmente esse estado armazenado.

