Pular para o conteúdo principal
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"
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.ryzeapi.cloud/llms.txt

Use this file to discover all available pages before exploring further.

Auth: TokenAccount ou TokenInstance (header ou query) • Protocolo: WSS/WS • Rate-limit: Global (100/min sobre o upgrade)

Descrição

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.

Exemplos cURL (handshake)

websocat ou wscat dão experiência interativa. cURL serve só para inspecionar o handshake.

Handshake (inspeção)

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.
curl -v --include \
  --header "Connection: Upgrade" \
  --header "Upgrade: websocket" \
  --header "Sec-WebSocket-Key: $(openssl rand -base64 16)" \
  --header "Sec-WebSocket-Version: 13" \
  --header "token: $Token_Instance" \
  "https://ryzeapi.cloud/ws/$Instance_Name"

wscat (interativo)

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 wscat
wscat -c "wss://api.example.com/ws/$Instance_Name?token=$Token_Instance"

Exemplos de cliente

Browsers não permitem customizar headers no WebSocket, use ?token=:
const BASE = "wss://api.example.com";
const INSTANCE = "$Instance_Name";
const TOKEN = "a1b2c3d4-..."; // Account ou Instance

let ws;
let reconnectDelay = 1000; // 1s, dobra até 30s

function connect() {
  ws = new WebSocket(`${BASE}/ws/${INSTANCE}?token=${encodeURIComponent(TOKEN)}`);

  ws.addEventListener("open", () => {
    console.log("WS conectado");
    reconnectDelay = 1000;
  });

  ws.addEventListener("message", (ev) => {
    try {
      const env = JSON.parse(ev.data);
      switch (env.event) {
        case "message.exchange":  handleMessage(env.data); break;
        case "instance.state":    handleState(env.data);   break;
        // ... demais tipos
      }
    } catch (e) {
      console.error("Frame não-JSON:", ev.data);
    }
  });

  ws.addEventListener("close", (ev) => {
    console.warn(`Fechado (code=${ev.code}). Reconectando em ${reconnectDelay}ms...`);
    setTimeout(connect, reconnectDelay);
    reconnectDelay = Math.min(reconnectDelay * 2, 30000);
  });

  ws.addEventListener("error", (ev) => {
    console.error("WS error:", ev);
    // 'close' dispara em seguida
  });
}

connect();

Envelope dos frames recebidos

Cada frame de texto é um JSON idêntico ao webhook:
{
  "event": "message.exchange",
  "data": { /* payload específico */ },
  "instanceData": {
    "baseUrl": "https://api.example.com",
    "instance": "$Instance_Name",
    "token":    "<instance-token>"
  }
}
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.

Parâmetros de rota

instance
string
obrigatório
Nome da instância. Deve existir e ter WebSocket habilitado.

Headers

NomeObrigatórioExemploDescrição
token ou Authorizationsim, salvo se usar ?token=token: a1b2c3...Auth flexível.
UpgradesimwebsocketExigido pelo protocolo.
ConnectionsimUpgradeIdem.
Sec-WebSocket-Keysim(gerado pelo cliente)Idem.
Sec-WebSocket-Versionsim13Único valor aceito.
Origincondicionalhttps://app.exemplo.comValidado contra allowlist em browsers. Clients sem Origin são aceitos.

Query parameters

token
string
Token de autenticação. Obrigatório quando o cliente não pode enviar token ou Authorization no header (caso dos browsers).

Pré-condições

  1. Existe uma config em websocket_configs para a instância (criada via POST /api/events/websocket/:instance) com enabled=true.
  2. Token válido, TokenAccount ou TokenInstance da instância (mesma matriz do REST).
  3. Se vier de browser, o Origin do request está em ALLOWED_WS_ORIGINS ou é same-origin.
A validação acontece antes do upgrade HTTP→WS. Após o upgrade não há re-autenticação, a sessão TCP é confiável até ser fechada.

Autenticação

ValidateTokenFlexible() aceita o token em três fontes:
FonteExemplo
Header tokentoken: a1b2c3d4-...
Header Authorization: BearerAuthorization: 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.

Validação de Origin (ALLOWED_WS_ORIGINS)

Independente do CORS (que afeta só REST), o WebSocket tem sua própria allowlist controlada pela env var ALLOWED_WS_ORIGINS.
ALLOWED_WS_ORIGINSComportamento
Vazio / não definidoApenas same-origin (Origin igual ao Host) é aceito.
"https://app.exemplo.com,https://dashboard.exemplo.com"Allowlist explícita, separada por vírgula.
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.

Heartbeat

LadoMensagemIntervalo
Servidor → clientePINGa cada ~54s (pingPeriod)
Cliente → servidorPONGdentro de 60s (pongWait)
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.

Buffers e backpressure

LimiteValorEfeito ao estourar
Read buffer (max client message)4096 bytesServidor fecha a conexão.
Send buffer por cliente256 mensagensCliente lento é dropado pelo hub.
O servidor não consome mensagens enviadas pelo cliente (apenas PONG e fechamento). Enviar payloads JSON do cliente para o servidor não tem efeito.

Catálogo de eventos

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.

Reconexão e resiliência

O servidor não replica eventos perdidos durante quedas, o cliente WS é fire-and-forget. Para garantia de entrega, use webhook em paralelo.
Sempre tenha handler de close com reconexão automática, idealmente com backoff exponencial e jitter, limitado a 30s entre tentativas.
Trate close codes: 1006 (queda de rede), 1011 (erro do servidor), 1008 (policy violation), 4xxx (custom, raros).
Catch-up via REST depois de reconectar, use GET /api/chat/history/:instance para puxar mensagens recentes que possam ter sido perdidas.
Buffer local no cliente, nunca bloqueie o handler message com operações lentas; jogue em fila e processe em outra thread/worker.

Efeitos colaterais

  • 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.
  • Métricas Prometheus: contadores de conexões ativas por instância (ver /api/observability/overview).

Notas

  • 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.

Quando usar webhook vs WebSocket

CritérioWebSocketWebhook
Latênciams (push direto)100-500ms (HTTP + fila)
PersistênciaEventos perdidos se offlineFila + retry 5x + DLQ
Multi-consumerVários clientes em broadcastAté 3 webhooks habilitados (labels)
AuthToken no upgradeHeader Authorization opcional
SetupCliente WS + config habilitadaEndpoint HTTP público + URL
Dev-friendlinessExcelente (wscat, DevTools)Requer tunneling em dev
  • Webhook: integrações server-to-server onde perda é inaceitável (CRM, ERP, analytics, log sink).
  • WebSocket: UIs em tempo real (dashboard, inbox ao vivo, tela de atendimento) onde latência baixa é prioridade e perdas ocasionais são aceitáveis.
  • Os dois em paralelo: webhook persiste estado, WS faz a UI saltar.

Erros antes do upgrade

Todas ocorrem antes do 101 Switching Protocols, o cliente recebe um HTTP normal.
HTTPerror.messageQuando
400WebSocket is not enabled for this instance. Configure it first using POST /api/events/websocket/<instance>Sem config ou enabled=false.
401Missing token in header, Authorization header, or query parameterNenhuma das 3 fontes forneceu token.
401Invalid tokenToken inválido.
403— (body vazio, do upgrader)Origin fora da allowlist.
404Instance not found:instance inexistente.
429Rate limit exceeded. Try again later.Rate-limit global.
500Failed to get instance / Failed to get websocket configurationErro de banco.
{
  "success": false,
  "error": {
    "message": "WebSocket is not enabled for this instance. Configure it first using POST /api/events/websocket/$Instance_Name"
  }
}

Erros após o upgrade

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.

Referências

Configurar WebSocket

POST /api/events/websocket/:instance

Catálogo de eventos

Schemas dos 6 tipos.

Visao geral de Eventos

Webhook x WebSocket, envelope, boas práticas.

Autenticação

Matriz de tokens, header token, ?token=.