Upgrade /ws/:instance, protocolo, autenticação, validação de Origin, heartbeat e reconexão
GET
/
ws
/
:instance
Conectar via WebSocket
curl --request GET \
--url https://api.example.com/ws/:instance
{ "success": false, "error": { "message": "WebSocket is not enabled for this instance. Configure it first using POST /api/events/websocket/$Instance_Name" }}
Endpoint de upgrade HTTP → WebSocket para receber eventos em tempo real. Os frames enviados pelo servidor têm o mesmo envelope dos webhooks, texto JSON com event, data e instanceData.A configuração (habilitar, filtrar eventos, ativar mediaBase64) é feita em POST /api/events/websocket/:instance. Esta página cobre apenas a camada de conexão.
Pré-requisito: a instância precisa ter o WebSocket configurado com enabled=true. Sem isso, o upgrade falha com 400 antes de virar conexão WS.
Faz o handshake bruto de upgrade HTTP→WebSocket apenas para inspecionar status, headers e validar que a instância está aceitando conexões. Não mantém o canal aberto, é uma sondagem one-shot.
Abre uma sessão WebSocket interativa real com wscat (ou cliente equivalente em cada linguagem) e fica imprimindo cada frame JSON recebido. Forma mais prática para debugar eventos em tempo real durante o desenvolvimento.
# npm i -g wscatwscat -c "wss://api.example.com/ws/$Instance_Name?token=$Token_Instance"
instanceData.token é o token da própria instância, útil quando o cliente consome múltiplas instâncias e precisa identificar a origem ou fazer chamadas REST de volta.
Quando ENCRYPTION_KEY está configurada, o token vem descriptografado no payload. Filtre/redija em logs do cliente se você loggar o frame inteiro.
ValidateTokenFlexible() aceita o token em três fontes:
Fonte
Exemplo
Header token
token: a1b2c3d4-...
Header Authorization: Bearer
Authorization: Bearer a1b2c3d4-...
Query param ?token=
wss://api.example.com/ws/minha?token=a1b2c3d4-...
O query param é praticamente obrigatório para clients de browser, já que a API new WebSocket(url) do navegador não permite customizar headers.Clients server-side (Node, Go, Python, etc.) devem preferir o header token, query param vaza em logs de proxy/CDN.
Clientes sem header Origin (curl, Postman, libs Node/Python/Go) são sempre aceitos, Origin é mecanismo do browser, não universal. A segurança para esses clientes é o token.Bloqueios são logados como WebSocket upgrade blocked from origin <origem> (host <host>). O cliente recebe 403 Forbidden (sem body) e a TCP é fechada.
Sem PONG em 60s → o servidor dropa a conexão. Não há resumo de sessão: o cliente deve reconectar com backoff e os eventos perdidos no intervalo não voltam.A maioria das libs WebSocket (gorilla/websocket, ws do Node, websockets do Python, browser nativo) responde PONG automaticamente, o cliente quase nunca precisa implementar isso manualmente.
Os 6 tipos possíveis (message.exchange, message.status, call.update, group.flow, instance.state, label.update) compartilham este envelope. Schemas e exemplos completos em /api/events/catalog.
Hub em memória: o handler registra o cliente em WebSocketHub (map[instanceName]map[*WebSocketClient]bool). A conexão não é persistida. Reinício do processo derruba todos.
Goroutines: cada conexão lança 2 goroutines (WritePump e ReadPump) que vivem até o close.
Sem DB write: o upgrade em si não escreve nada. Broadcasts subsequentes passam pelo dispatcher de webhook (que toca DB) em paralelo, WS é apenas fanout adicional.
Sem retry/persistência: cliente offline 5min = perde 5min de eventos. Para garantia, use webhook.
Multi-cliente: vários clientes podem conectar na mesma instância. Todos recebem todos os eventos (broadcast). Não há atomicidade de “quem processou primeiro”.
Filtros são globais por instância: o filtro events[] configurado em POST /api/events/websocket/:instance vale para todos os clientes, não é configurável por conexão.
Frame size do servidor: o limite de 4096 bytes vale apenas para mensagens enviadas pelo cliente. O servidor envia frames potencialmente bem maiores (mídia em base64 passa de 100KB facilmente). Leia frames sem limite no cliente.
Todas ocorrem antes do 101 Switching Protocols, o cliente recebe um HTTP normal.
HTTP
error.message
Quando
400
WebSocket is not enabled for this instance. Configure it first using POST /api/events/websocket/<instance>
Sem config ou enabled=false.
401
Missing token in header, Authorization header, or query parameter
Nenhuma das 3 fontes forneceu token.
401
Invalid token
Token inválido.
403
— (body vazio, do upgrader)
Origin fora da allowlist.
404
Instance not found
:instance inexistente.
429
Rate limit exceeded. Try again later.
Rate-limit global.
500
Failed to get instance / Failed to get websocket configuration
Erro de banco.
{ "success": false, "error": { "message": "WebSocket is not enabled for this instance. Configure it first using POST /api/events/websocket/$Instance_Name" }}
Depois do 101, qualquer falha de protocolo fecha a conexão com um close code padrão (1001 going away, 1006 abnormal closure, 1011 server error). O servidor não escreve body, o cliente trata pelo close code.Causas comuns:
Frame do cliente maior que 4096 bytes.
pongWait (60s) expirou sem resposta ao PING.
Buffer de envio do cliente cheio (cliente lento), hub faz unregister.
Instância foi deletada enquanto o cliente estava conectado.