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: readycomaccountId(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: 5000instrui 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
| Aspecto | Webhook | SSE |
|---|---|---|
| Direção | Push (gateway → você) | Pull persistente (você → gateway) |
| Reentrega | Sim (8 retries, DLQ) | Não — se cair, eventos durante o gap somem |
| Idempotência | Você precisa garantir | Não há replay |
| Autenticação | HMAC assinatura | API key |
| Casos | Backend → backend | Browser dashboard, dev local |
| Persistência | WebhookDelivery no DB | Apenas em memória |
| Limite de conexões | — | 1 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/eventspara 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
phoneIdoutype. - 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.