Pular para o conteúdo
Decoding Chat API

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.

O cliente abre o socket, aguarda o Hello, envia Identify e mantém heartbeats periódicos durante toda a vida da conexão.

  1. Leia endpoints.gateway a partir do documento de descoberta da instância e abra um WebSocket para ele com ?v=1&encoding=json.
  2. Leia o Opcode 10 Hello e obtenha o heartbeat_interval informado.
  3. Envie o Opcode 2 Identify com o token e as properties.
  4. Leia o evento Ready e guarde seu session_id para uma futura Retomada.
  5. Envie o Opcode 1 Heartbeat com o último número de sequência de Dispatch a cada intervalo de heartbeat_interval milissegundos.
{
"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.

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.

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.

Acrescente os parâmetros de conexão à URL descoberta.

CampoTipoDescrição
vintegerVersão do protocolo Gateway, que é 1
encoding?1stringCodificação do payload
compress?2stringFluxo de compressão, aceitando zstd-stream ou none (padrão: sem compressão)
stream?3stringFlag 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.

Toda mensagem lógica utiliza o payload padrão do Gateway.

CampoTipoDescrição
opintegerOpcode do Gateway
d?1anyPayload 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?integerNúmero de sequência não negativo da sessão, presente apenas em Dispatch
t?stringNome 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.

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.

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.

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.

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.

Evento e condiçãoAçãoPróximo estado
WebSocket aceito. v=1 e capacidade de conexão disponívelEnviar HelloUnauthenticated
Versão inválida. v ausente ou diferente de 1Fechar com 4012 e motivo Invalid API versionClosed
Limite de conexões simultâneas atingido. O IP de origem já possui 256 conexõesFechar com 4008 e motivo Too many connectionsClosed
Evento e condiçãoAçãoPróximo estado
Identify. Payload de Identify válido e capacidade de Identify disponívelIniciar criação de sessãoStarting
Identify. Gateway em processo de drain, nó em capacidade máxima, início de sessões pausado ou conta fora do rollout de sessãoReter o payload e tentar novamente em segundo planoUnauthenticated
Identify. Orçamento de Identify do IP de origem esgotadoDescartar o payload sem responderUnauthenticated
Resume. Payload de Resume válidoLocalizar a sessão retida indicada por session_idStarting
Comando autenticado. Qualquer comando que não seja Heartbeat, Identify ou ResumeFechar com 4003 e motivo Not authenticatedClosed
Evento e condiçãoAçãoPróximo estado
Criação de sessão bem-sucedida. Identify foi aceitoEnviar ReadyReady
Falha permanente na criação de sessão. Token inválido, shard inválido, sharding obrigatório ou excesso de sessõesFechar com o código e motivo listados em Hello e criação de sessãoClosed
Falha na criação de sessão com erro não classificado pelo GatewayFechar com 4000 e motivo Failed to start sessionClosed
Falha temporária na criação de sessão. Drain, capacidade máxima, falha de RPC, timeout ou conta fora do rolloutReter o Identify e tentar novamente em segundo planoUnauthenticated
Retomada bem-sucedida. A sessão retida aceitou o número de sequênciaReproduzir Dispatches retidosReplaying
A sessão não pode ser retomada. Resume indicou sessão desconhecida/expirada ou seq abaixo do piso de replayEnviar Invalid Session com d: falseUnauthenticated
Evento e condiçãoAçãoPróximo estado
Replay concluído. Todos os Dispatches retidos foram enviadosEnviar ResumedReady
Comando autenticado. A sessão está vinculadaProcessar o comandoReplaying
Identify. Uma sessão já está vinculadaFechar com 4005 e motivo Already authenticatedClosed
Resume. Payload de Resume válidoVincular a sessão indicada a este socket no lugar da atualStarting
Evento e condiçãoAçãoPróximo estado
Comando autenticado. O comando é válido na sessãoProcessar o comandoReady
Identify. Uma sessão já está vinculadaFechar com 4005 e motivo Already authenticatedClosed
Resume. Payload de Resume válidoVincular a sessão indicada a este socket no lugar da atualStarting
Evento e condiçãoAçãoPróximo estado
O processo da sessão terminou. A sessão foi encerrada enquanto este socket a mantinhaEnviar Invalid Session com d: falseUnauthenticated
Drain do Gateway ou transferência de sessão. O nó deixa de atender a sessãoEnviar Reconnect e fechar com 4000Closed
A sessão foi retomada em outro local. Outro socket vinculou esta sessão via ResumeEnviar Reconnect e fechar com 4000Closed
Evento e condiçãoAçãoPróximo estado
Heartbeat. Nenhuma sessão vinculada, ou payload é null, ou a sessão vinculada aceita a sequênciaEnviar Heartbeat ACKMesmo estado
Prazo de Heartbeat expirado. A conexão aguarda confirmação e mais de 45.000 ms se passaram desde o último ACKFechar com 4009 e motivo Heartbeat timeoutClosed
Frame ou payload inválido. Falha de validação de tamanho, descompressão ou decodificaçãoFechar com 4002 e motivo correspondente em Payload do Gateway ou FramingClosed
Transporte encerrado. Uma sessão existeReter a sessão por 60.000 msClosed

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.

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.

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.

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.

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.

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.

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.

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.