Comandos do cliente
Os clientes enviam comandos através do WebSocket do Gateway, com um opcode inteiro em op e os dados do comando em d. Um comando pode produzir um Dispatch, um frame de fechamento ou nenhuma resposta.
Com exceção de Heartbeat, Identify e Resume, todos os comandos exigem uma sessão autenticada. Enviar um comando antes da autenticação encerra a conexão com o código 4003 e motivo Not authenticated. Heartbeat e Resume são aceitos em qualquer estado aberto, e Identify é aceito apenas enquanto a conexão não estiver autenticada.
Índice de comandos
Seção intitulada “Índice de comandos”| Opcode | Comando | Resultado |
|---|---|---|
| 1 | Heartbeat | Opcode 11 Heartbeat ACK |
| 2 | Identify | Ready, um frame de fechamento, ou nenhuma resposta caso o Decoding Chat descarte um Identify com taxa limitada ou o retenha para tentar iniciar a sessão novamente |
| 3 | Presence Update | Sem resposta direta |
| 4 | Voice State Update | Voice State Update e Voice Server Update quando o estado for alterado |
| 6 | Resume | Dispatches reproduzidos seguidos por Resumed, Invalid Session ou um frame de fechamento |
| 8 | Request Guild Members | Um ou mais eventos Guild Members Chunk |
| 14 | Lazy Request | Guild Sync e Guild Member List Update |
| 15 | Request Guild Counts | Guild Counts Update |
| 16 | Request Channel Member Counts | Channel Member Counts Update |
Tratamento de payloads
Seção intitulada “Tratamento de payloads”Um frame que falhar nas checagens de tamanho, descompressão ou decodificação fecha a conexão sem consumir orçamento de taxa. Um frame que decodificar em algo que não seja um objeto fecha com 4002 e motivo Decode failed, e um objeto sem op fecha com 4002 e motivo Invalid payload.
O Decoding Chat debita todo comando que passar por essas checagens nos orçamentos de payload de IP de origem, sessão e conexão antes de processar o opcode. Cada sessão possui seu próprio orçamento de sessão (duas sessões da mesma conta nunca compartilham orçamento), e essa verificação é ignorada enquanto a conexão não estiver autenticada.
Um opcode fora do registro oficial fecha com 4001 e motivo Unknown opcode após a vinculação de sessão, e com 4003 enquanto a conexão não estiver autenticada. Um payload com op mas sem d também fecha com 4001, exceto Identify, que fecha com 4005.
Um campo booleano de comando é ativado apenas por true e pela string "true" nos locais indicados. Qualquer outro valor resolve para false, exceto no objeto de assinatura de servidor do Lazy Request, que possui regra própria.
Heartbeat
Seção intitulada “Heartbeat”O Opcode 1 carrega a última sequência de Dispatch que o cliente processou, ou null antes do primeiro Dispatch.
| Campo | Tipo | Descrição |
|---|---|---|
| d | ?integer | A última sequência de Dispatch processada pelo cliente, ou null antes do primeiro Dispatch |
{ "op": 1, "d": 42}Antes da autenticação, o Gateway aceita qualquer valor de d e responde com o Opcode 11. Um payload sem a chave d fecha com 4001 e motivo Unknown opcode.
Após a autenticação, um d que não seja null nem um número inteiro fecha com 4007 e motivo Invalid sequence. Qualquer número inteiro é aceito, mas confirmações de sequência nunca retrocedem. Dispatches iguais ou inferiores à maior sequência confirmada deixam de estar disponíveis para Resume.
Quando a sessão termina, o Decoding Chat envia o Opcode 9 com d: false, após o qual os heartbeats voltam a ser confirmados normalmente. Um heartbeat que chegue na janela de transição entre o encerramento da sessão e esse frame fecha com 4007.
Consulte Visão geral do Gateway para o contrato de temporização.
Identify
Seção intitulada “Identify”O Opcode 2 autentica e cria uma nova sessão.
| Campo | Tipo | Descrição |
|---|---|---|
| token | string | Token da conta ou do bot, sem prefixo de autenticação HTTP |
| properties | identify properties object | Informações de software e capacidades do cliente que está conectando |
| presence?1 | ?initial presence object | Presença a ser publicada no início da sessão |
| ignored_events?2 | ?array[string] | Nomes de eventos de Dispatch que esta sessão não deseja receber (no máximo 256 entradas) |
| flags? | integer | Bitfield de flags de sessão não negativo (padrão 0) |
| initial_guild_id?3 | ?snowflake | O snowflake de um servidor no qual a sessão ingressa já no estado ativo |
| shard?4 | ?array[integer] | O par [shard_id, shard_count] |
1 null e chave omitida selecionam o status salvo e status personalizado salvo da conta
2 Nomes são convertidos para maiúsculo e desduplicados. Consulte Filtragem de eventos para a regra exata de supressão
3 A sessão torna-se ativa nesse servidor sem a necessidade de um Lazy Request, conforme descrito em Filtragem de eventos, e não recebe Guild Sync inicial. Um valor que não seja uma string Snowflake decimal canônica é ignorado sem falhar o Identify
4 shard_count é um inteiro de 1 até 16.384, e shard_id é um inteiro maior ou igual a 0 e menor que shard_count
{ "op": 2, "d": { "token": "...", "properties": { "os": "Linux", "browser": "Decoding Client", "device": "desktop" }, "presence": { "status": "online", "afk": false, "mobile": false }, "ignored_events": ["TYPING_START"], "flags": 2, "initial_guild_id": "1189375284394692608" }}token e properties são obrigatórios. O Decoding Chat ignora campos desconhecidos. Não existe campo intents nem sistema de intents.
As seguintes falhas encerram a conexão com 4002 e motivo Invalid identify payload:
tokenoupropertiesausente.propertiesque não seja um objeto.propertiescujoos,browseroudeviceesteja ausente ou não seja uma string.- Valor de
ignored_eventsque não seja um array de strings ou que contenha mais de 256 itens. - Valor de
flagsque não seja um número inteiro não negativo.
Um par de shard malformado fecha com 4010 e motivo Invalid shard.
O Decoding Chat recusa sessões de bot que alcancem mais de 2.500 servidores após o filtro de shard. A conexão fecha com 4011 e motivo Sharding required. Sessões de usuário nunca são recusadas pela contagem de servidores.
Um token rejeitado pelo backend fecha com 4004 e motivo Invalid token. Uma conta comum (não-bot) que já possua 100 sessões ativas fecha com 4008 e motivo Too many sessions (credenciais de bot não sofrem esse limite). Um Identify enviado em um socket que já possua sessão vinculada fecha com 4005 e motivo Already authenticated, com ou sem d.
Flags de sessão
Seção intitulada “Flags de sessão”| Valor | Nome | Descrição |
|---|---|---|
| 1 << 1 | DEBOUNCE_MESSAGE_REACTIONS | Agrupa sequências de adições de reações em Message Reaction Add Many |
O bit 0 e todos os bits acima de 1 são indefinidos. Bits indefinidos são aceitos e ignorados sem fechar a conexão.
DEBOUNCE_MESSAGE_REACTIONS se aplica a reações em mensagens diretas (DM) ou mensagens diretas em grupo (GDM). Reações em canais de servidores nunca são agrupadas e chegam individualmente como Message Reaction Add.
Objeto de propriedades do Identify
Seção intitulada “Objeto de propriedades do Identify”Estrutura
Seção intitulada “Estrutura”| Campo | Tipo | Descrição |
|---|---|---|
| os | string | Sistema operacional onde o cliente está sendo executado |
| browser | string | Identificador da biblioteca ou cliente |
| device | string | Identificador do dispositivo ou aplicação |
| e2ee_capable?1 | boolean | Indica se o cliente suporta voz criptografada ponta a ponta |
| mobile?2 | boolean | Indica se a sessão é móvel (padrão: false) |
| latitude?3 | string | Latitude do cliente como string decimal de 1 até 32 caracteres |
| longitude?3 | string | Longitude do cliente como string decimal de 1 até 32 caracteres |
1 Sessões sem esse suporte são recusadas em canais de voz com criptografia de ponta a ponta com VOICE_E2EE_REQUIRED
2 Lido apenas quando presence estiver ausente ou for null, decidindo a flag mobile da sessão. Caso contrário, o objeto de presença inicial tem preferência
3 Usado para ordenar o array rtc_regions do Ready por proximidade geográfica
os, browser e device são strings obrigatórias. Os demais campos são sugestões opcionais. Propriedades desconhecidas são ignoradas.
latitude e longitude são aceitos aqui exclusivamente como strings (ex.: " -23.55"). Números puros falham na validação e invalidam o início da sessão. Ambos devem ser enviados juntos para ter efeito; strings não numéricas são consideradas ausentes. Clientes sem localização omitem ambos, e o Ready ordena rtc_regions pelo ID da região.
Objeto de presença inicial
Seção intitulada “Objeto de presença inicial”Estrutura
Seção intitulada “Estrutura”| Campo | Tipo | Descrição |
|---|---|---|
| status?1 | string | Status inicial: online, idle, dnd, invisible ou offline |
| afk? | boolean | Indica se a sessão está ausente (padrão: false) |
| mobile? | boolean | Indica se a presença é móvel (padrão: false) |
| custom_status?2 | ?custom status object | Status personalizado que esta sessão publica |
1 O status salvo da conta é usado quando status estiver ausente, for null/não-string, for a string unknown ou quando for online enquanto o status salvo não for online. String vazia resolve para online, e os demais valores válidos são usados como enviados
2 Lido apenas quando a conta não possuir status personalizado salvo, sendo armazenado como enviado sem validação
O Identify aceita offline como status inicial distinto, e o Presence Update normaliza offline para invisible. Uma sessão cujo status resolvido seja offline ou invisible publica status: "offline" e custom_status: null para os outros usuários.
Objeto de status personalizado
Seção intitulada “Objeto de status personalizado”Estrutura
Seção intitulada “Estrutura”| Campo | Tipo | Descrição |
|---|---|---|
| text? | ?string | Texto do status personalizado (1 a 128 caracteres) |
| expires_at?1 | ?ISO8601 timestamp | Momento em que o status personalizado expira |
| emoji_id?2 | ?snowflake | O snowflake do emoji personalizado |
| emoji_name?3 | ?string | O emoji Unicode (1 a 32 caracteres) |
1 Timestamp deve estar no futuro
2 O Snowflake deve corresponder a um emoji existente. O Decoding Chat remove o campo do objeto publicado caso a conta não tenha direito a expressões globais
3 Um único emoji Unicode. O campo é descartado antes da validação se emoji_id for fornecido
Apenas esses campos são lidos. Presence Update valida o objeto contra a conta antes de publicá-lo.
A presença publicada adiciona o campo emoji_animated a esse objeto.
O Opcode 6 restaura uma sessão retida.
| Campo | Tipo | Descrição |
|---|---|---|
| token | string | Token proprietário da sessão retida |
| session_id | string | O ID da sessão recebido no Ready |
| seq | integer | Última sequência de Dispatch que o cliente processou |
Todos os campos são obrigatórios. Campo ausente, token ou session_id que não sejam strings, ou seq que não seja número inteiro encerram a conexão com 4002 e motivo Invalid resume payload.
Sessão desconhecida ou expirada envia o Opcode 9 com d: false e mantém o socket não autenticado. Um seq abaixo do piso de replay gera o mesmo frame. Token inválido fecha com 4004 e motivo Invalid token. Um seq maior que a sequência atual ou menor que a já confirmada fecha com 4007 e motivo Invalid sequence. Um seq negativo fecha com 4000 e motivo Session unavailable, o mesmo ocorrendo para sessões inalcançáveis. Nenhuma dessas falhas destrói a sessão retida associada a session_id.
Um Resume bem-sucedido reproduz em ordem todos os Dispatches retidos estritamente acima de seq e finaliza com Resumed. Ele substitui o socket da sessão, e o socket antigo recebe o Opcode 7 seguido por desconexão.
Envie Resume preferencialmente em um socket novo.
Presence Update
Seção intitulada “Presence Update”O Opcode 3 altera a presença da sessão atual.
| Campo | Tipo | Descrição |
|---|---|---|
| status | string | Status a publicar: online, idle, dnd, invisible ou offline |
| afk? | boolean | Indica se a sessão está ausente (padrão: false) |
| mobile? | boolean | Indica se a sessão é móvel (padrão: false) |
| custom_status?1 | ?custom status object | Status personalizado que substitui o atual |
1 Objeto idêntico ao atual em text, expires_at, emoji_id e emoji_name é reaproveitado sem revalidação
{ "op": 3, "d": { "status": "idle", "afk": true, "mobile": false, "custom_status": { "text": "ausente no momento" } }}status é obrigatório. Payloads que não sejam objetos, objetos sem a chave status ou strings fora das opções válidas fecham com 4002 e motivo Invalid presence payload. String vazia resolve para online.
Valores de status não-string são tratados: null e booleano publicam a sessão como offline, e qualquer outro valor resolve para online.
offline é normalizado para invisible, de modo que o Presence Update não publica uma sessão como offline enquanto ela estiver conectada.
custom_status é substituído apenas quando a chave estiver presente. Omitir a chave mantém o status personalizado atual, null o remove, e valores inválidos são ignorados. Se o backend rejeitar o objeto (como um emoji_id inexistente), o status atual é mantido e a conexão segue aberta.
O Presence Update possui limite de 5 comandos aceitos a cada 20 segundos por WebSocket. Atualizações além do limite são descartadas sem encerrar a conexão, após consumirem os orçamentos compartilhados de payload.
Voice State Update
Seção intitulada “Voice State Update”O Opcode 4 conecta, move, atualiza ou desconecta a participação de voz da sessão atual do Gateway.
| Campo | Tipo | Descrição |
|---|---|---|
| guild_id? | ?snowflake | O servidor que contém o canal de voz (null seleciona contexto de chamada em DM/GDM) |
| channel_id? | ?snowflake | O canal para conectar ou mover (null desconecta da chamada/canal atual) |
| connection_id?1 | ?string | A conexão de voz existente à qual esta atualização se aplica |
| self_mute?2 | boolean | Se o cliente mutou o próprio microfone (padrão: false) |
| self_deaf?2 | boolean | Se o cliente ensurdeceu o próprio áudio (padrão: false) |
| self_video?2 | boolean | Se o cliente está transmitindo vídeo de câmera (padrão: false) |
| self_stream?4 | boolean | Se esta conexão anuncia compartilhamento de tela (padrão: false) |
| is_mobile?2 | boolean | Se este é um cliente de voz móvel (padrão: false) |
| viewer_stream_keys?3 | ?array[string] | Stream keys que esta conexão está assistindo (omitir mantém a lista, null a limpa) |
| latitude? | number or string | Latitude do cliente para seleção de região de voz |
| longitude? | number or string | Longitude do cliente para seleção de região de voz |
1 channel_id sem connection_id abre uma nova conexão; com connection_id, move ou atualiza a conexão. Desconectar de um servidor (guild_id não nulo com channel_id: null) exige connection_id e a omissão resulta em VOICE_MISSING_CONNECTION_ID
2 Apenas true e a string "true" ativam a flag. Qualquer outro valor resolve para false
3 Cada entrada é uma stream key cujo escopo, servidor e canal correspondem a esta atualização. Entradas inválidas rejeitam a atualização com VOICE_INVALID_STATE, e conexões inexistentes com VOICE_CONNECTION_NOT_FOUND
4 Apenas true e "true" ativam a flag. O Decoding Chat publica false se o membro não possuir permissão STREAM no canal. A transmissão de tela utiliza a mesma conexão de áudio
{ "op": 4, "d": { "guild_id": "1189375284394692608", "channel_id": "1189375284394692610", "self_mute": false, "self_deaf": false, "self_video": false, "self_stream": false }}Todos os campos são opcionais. guild_id ou channel_id não nulos devem ser strings decimais canônicas de snowflake ou inteiros positivos. Outros formatos falham na validação e a atualização é descartada sem código de fechamento.
guild_id: null com channel_id: null e um connection_id desconecta da chamada em DM ou GDM específica. A mesma estrutura sem connection_id desconecta a sessão de todas as salas de voz em que estiver conectada.
latitude e longitude aceitam número ou string, sendo convertidos internamente para string.
Conectar ou obter uma nova permissão emite o evento Voice Server Update com o token e endpoint para a conexão de mídia, além de Voice State Update para todas as sessões que podem visualizar o canal.
As duas primeiras atualizações em uma janela de um segundo são aplicadas imediatamente. Atualizações subsequentes podem ser agrupadas ou substituídas por atualizações mais novas para o mesmo guild_id e connection_id.
Request Guild Members
Seção intitulada “Request Guild Members”O Opcode 8 solicita lotes (chunks) delimitados de membros de servidores.
| Campo | Tipo | Descrição |
|---|---|---|
| guild_id?1 | snowflake | ID de um único servidor a ser consultado |
| guild_ids?1 | array[snowflake] | Array não vazio de IDs de servidores a consultar |
| query?2 | string | Prefixo do nome de exibição para correspondência (padrão: string vazia) |
| limit?3 | integer | Limite de resultados (0 a 100, padrão: 0) |
| user_ids?4 | array[snowflake] | IDs explícitos de usuários para buscar, no máximo 100 (padrão: vazio) |
| presences?5 | boolean | Se os resultados incluem presenças dos membros (padrão: false) |
| nonce? | string | Valor de até 32 bytes ecoado em cada chunk retornado |
1 O array guild_ids tem prioridade; guild_id só é lido se guild_ids estiver ausente ou vazio
2 Comparação insensível a maiúsculas/minúsculas no apelido do servidor, depois nome global e por fim nome de usuário
3 limit: 0 com query preenchida retorna até 25 resultados; limit: 0 com query vazia solicita a lista completa de membros (até 100.000)
4 user_ids não vazio seleciona diretamente esses membros e ignora query e limit
5 Presenças com status offline ou invisible não são incluídas no retorno
{ "op": 8, "d": { "guild_id": "1189375284394692608", "query": "ann", "limit": 50, "presences": true, "nonce": "a1b2c3" }}O comando nunca encerra a conexão. Entradas inválidas são ajustadas ou descartadas:
- ID de servidor inválido descarta a requisição por completo.
- IDs de servidores duplicados são agrupados.
user_idscom mais de 100 entradas anula a requisição.limitnão numérico vira0, e valores acima de 100 são limitados a100.querynão-string vira string vazia.noncecom mais de 32 bytes vira null.
O nonce só é ecoado quando a requisição especificar exatamente um único servidor.
Para solicitar a lista completa de membros (query vazia, limit: 0 e user_ids vazio), contas de usuários precisam possuir as permissões MANAGE_ROLES, KICK_MEMBERS e BAN_MEMBERS cumulativamente no servidor (ou ser dono/possuir ADMINISTRATOR).
Bots que solicitem a listagem completa sofrem taxa limite de uma requisição a cada 30 segundos por servidor. Requisições excedentes produzem o evento Rate Limited sem retornar membros.
Os resultados chegam como Guild Members Chunk em páginas de até 1.000 membros, cada uma com chunk_index e chunk_count. Esses chunks são entregues em tempo real e nunca são retidos no buffer de replay de retomada.
Lazy Request
Seção intitulada “Lazy Request”O Opcode 14 define as assinaturas por servidor que determinam a lista de membros, digitação e sincronização de tráfego para a sessão.
| Campo | Tipo | Descrição |
|---|---|---|
| subscriptions1 | map[snowflake, guild subscription object] | Opções de assinatura para cada servidor, indexadas pelo ID do servidor |
1 O Decoding Chat preserva as opções da sessão para cada servidor e as reaplica caso a sessão se reconecte a ele posteriormente
{ "op": 14, "d": { "subscriptions": { "1189375284394692608": { "active": true, "typing": true, "member_list_channels": { "1189375284394692610": [[0, 99]] } } } }}Objeto de assinatura de servidor
Seção intitulada “Objeto de assinatura de servidor”Estrutura
Seção intitulada “Estrutura”| Campo | Tipo | Descrição |
|---|---|---|
| active?1 | boolean | Se o servidor está no estado ativo para esta sessão |
| sync?1 | boolean | Se a sessão solicita um Guild Sync para o servidor |
| typing? | boolean | Se o servidor envia eventos Typing Start, sobrepondo a flag active |
| member_list_channels?2 | map[snowflake, array[array[integer]]] | Intervalos visíveis da lista de membros a assinar, indexados pelo ID do canal |
| members? | array[snowflake] | IDs explícitos de membros a assinar (máximo: 1.000) |
1 Devem ser booleanos quando presentes. Valores inválidos impedem o processamento das demais opções para o servidor
2 Intervalos enviados em uma janela de 100 ms para o mesmo canal são mesclados
As permissões VIEW_CHANNEL e VIEW_CHANNEL_MEMBERS controlam o recebimento da lista de membros em cada canal separadamente. Canais sem ambas as permissões não enviam Guild Member List Update.
member_list_channels mapeia o ID do canal para listas de intervalos [start, end], onde start >= 0, end >= start, end <= 100000 e end - start <= 99. Cada canal retém até 10 intervalos válidos.
Request Guild Counts
Seção intitulada “Request Guild Counts”O Opcode 15 solicita as contagens de membros totais e online para servidores.
| Campo | Tipo | Descrição |
|---|---|---|
| guild_ids | array[snowflake] | IDs dos servidores a consultar (desduplicados e truncados em até 100) |
| nonce? | string | Valor de 1 a 64 bytes ecoado no resultado |
{ "op": 15, "d": { "guild_ids": ["1189375284394692608"], "nonce": "counts-1" }}Os resultados chegam no evento Guild Counts Update.
Request Channel Member Counts
Seção intitulada “Request Channel Member Counts”O Opcode 16 solicita a contagem de membros totais e online para canais de um servidor.
| Campo | Tipo | Descrição |
|---|---|---|
| guild_id | snowflake | ID do servidor que contém os canais consultados |
| channel_ids | array[snowflake] | IDs dos canais a consultar (truncados em até 25) |
| channel_id? | snowflake | ID de canal único quando channel_ids estiver ausente |
| nonce? | string | Valor de 1 a 64 bytes ecoado no resultado |
{ "op": 16, "d": { "guild_id": "1189375284394692610", "channel_ids": ["1189375284394692612"], "nonce": "channel-counts-1" }}Os resultados chegam no evento Channel Member Counts Update.
Requisições delimitadas
Seção intitulada “Requisições delimitadas”Um WebSocket processa no máximo quatro comandos delimitados simultaneamente entre Request Guild Members, Lazy Request, Request Guild Counts e Request Channel Member Counts. Comandos excedentes são descartados silenciosamente. Cada requisição tem um prazo limite de 10.000 ms.

