Pular para o conteúdo principal

Events (SSE)

Alternativa em tempo real aos webhooks: stream de eventos via Server-Sent Events. Recomendado para dashboards internos e ambientes onde você não consegue expor um endpoint HTTPS público (desenvolvimento local, mobile apps com push delegado, etc).

Endpoint: GET /v1/events/stream


GET /v1/events/stream

Mantém uma conexão HTTP persistente. Cada evento publicado no wpp:events da sua account é emitido como SSE message.

Autenticação

EventSource (browser) não permite headers customizados. Use a query string:

GET /v1/events/stream?api_key=ak_live_...

Para clientes HTTP normais (curl, Node), pode usar X-API-Key header normalmente.

Headers de response

Content-Type: text/event-stream
Cache-Control: no-cache, no-transform
Connection: keep-alive
X-Accel-Buffering: no

Formato

retry: 5000

event: ready
data: {"accountId":"a1b2c3d4-..."}

event: message:received
id: evt-1234-...
data: {"id":"evt-1234-...","type":"message:received","accountId":"...","phoneId":"5f7b2e1c-...","timestamp":"2026-05-21T14:33:00.000Z","data":{...}}

event: message:status
id: evt-5678-...
data: {"id":"evt-5678-...","type":"message:status","data":{...}}

: ping 1716302005000

  • Primeiro evento sempre é event: ready com accountId (confirma autenticação).
  • Cada evento subsequente tem event: (tipo), id: (UUID estável), data: (envelope completo, mesmo formato do webhook).
  • Linhas começando com : são keep-alive (a cada 25s) — ignore.
  • retry: 5000 instrui o browser a reconectar em 5s se cair.

Exemplo curl

curl -N 'https://wpp.ogmma.com.br/v1/events/stream' \
-H "X-API-Key: ak_live_..."

-N (no buffering) é importante.

Exemplo Browser

const es = new EventSource(`https://wpp.ogmma.com.br/v1/events/stream?api_key=${API_KEY}`);

es.addEventListener('ready', (e) => {
console.log('Conectado:', JSON.parse(e.data));
});

es.addEventListener('message:received', (e) => {
const evt = JSON.parse(e.data);
console.log('Mensagem recebida:', evt.data);
});

es.addEventListener('channel:connected', (e) => {
console.log('Phone conectou:', JSON.parse(e.data).data.phoneNumber);
});

es.onerror = (err) => {
console.error('SSE error', err);
// browser auto-reconnect em 5s (retry: 5000 acima)
};

Exemplo Node (com eventsource)

import EventSource from 'eventsource';

const es = new EventSource('https://wpp.ogmma.com.br/v1/events/stream', {
headers: { 'X-API-Key': process.env.WPP_API_KEY },
});

es.addEventListener('message:received', (e) => {
console.log(JSON.parse(e.data));
});

Eventos disponíveis

Todos os mesmos do webhook (ver Webhooks → Eventos publicados). O SSE filtra automaticamente por accountId (você só recebe os da sua account).


Diferenças vs Webhook

AspectoWebhookSSE
DireçãoPush (gateway → você)Pull persistente (você → gateway)
ReentregaSim (8 retries, DLQ)Não — se cair, eventos durante o gap somem
IdempotênciaVocê precisa garantirNão há replay
AutenticaçãoHMAC assinaturaAPI key
CasosBackend → backendBrowser dashboard, dev local
PersistênciaWebhookDelivery no DBApenas em memória
Limite de conexões1 por aba (browser limit)

SSE NÃO substitui webhook. Para uso em produção crítica, sempre configure webhook (com retry + DLQ + replay). SSE é complementar para UX em tempo real.


Limitações

  • Sem replay: se sua conexão cair, eventos publicados durante o gap são perdidos. Use GET /v1/events para recuperar.
  • Conexão única por usuário: abrir múltiplas tabs no mesmo browser pode disparar limite (gateway não impõe explicitamente, mas Postgres pool pode esgotar com 100+ conexões abertas).
  • Sem filtro server-side: todos os eventos da account passam. Filtre no cliente por phoneId ou type.
  • Heartbeat: keep-alive a cada 25s (: ping <timestamp>). Intermediários (load balancers, proxies) costumam matar conexões idle em 30-60s — o ping previne isso.