Skip to main content
Webhooks são o jeito recomendado de acompanhar o que acontece depois do envio: em vez de consultar GET /v1/messages/{id} repetidamente, a Superlead envia um POST para a sua URL a cada transição de status e a cada mensagem recebida de um lead. É assim que se resolve o caso clássico do WhatsApp: a Meta aceita um envio fora da janela de 24 horas (201 accepted) e o falha segundos depois, de forma assíncrona — a falha chega no seu webhook, com o motivo.

Configuração

1

Cadastre seu endpoint

No painel da Superlead, em Integrações → Webhooks, adicione a URL HTTPS que vai receber os eventos.
2

Guarde o signing secret

Na criação, você recebe um signing secret (whsec_...) — ele é exibido nesse momento; guarde em local seguro. É com ele que você verifica a autenticidade de cada entrega.
3

Responda 2xx rápido

Ao receber um evento, responda 2xx imediatamente e processe de forma assíncrona. Entregas sem 2xx são reenviadas automaticamente com backoff.

Evento whatsapp.message.status

Disparado a cada transição de status de uma mensagem enviada: sent, delivered, read ou failedum evento por transição.
{
  "id": "evt_8c1f2a9b4d6e4f0a9b1c2d3e4f5a6b7c",
  "type": "whatsapp.message.status",
  "channel": "whatsapp",
  "apiVersion": "v1",
  "createTime": "2026-07-03T19:03:12.000Z",
  "messageStatus": {
    "wamid": "wamid.HBgMNTU1MzgxNTYwMzQ5FQIAERgU...",
    "status": "failed",
    "recipient": "+555381560349",
    "timestamp": "2026-07-03T19:03:11.000Z",
    "error": { "title": "Re-engagement message", "code": 131047 }
  }
}
  • Correlação: o wamid é o mesmo retornado por POST /v1/messages — use-o para casar o evento com o envio no seu sistema.
  • error: presente apenas quando status é failed. O code é o código numérico da Meta — o mesmo que aparece como upstream_code em GET /v1/messages/{id}. Para os significados, veja o catálogo de erros.
  • Para status de sucesso (sent, delivered, read), error vem null.

Evento whatsapp.message.received

Disparado quando um lead envia mensagem para o seu número. Exemplo com texto:
{
  "id": "evt_9f8e7d6c-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
  "type": "whatsapp.message.received",
  "channel": "whatsapp",
  "apiVersion": "v1",
  "createTime": "2026-07-03T14:30:00.000Z",
  "message": {
    "id": "msg_9f8e7d6c-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
    "wamid": "wamid.HBgMNTU...",
    "wabaId": "1234567890",
    "from": "+5511999999999",
    "fromUserId": null,
    "customerProfile": { "name": "João Silva" },
    "to": "+5511888888888",
    "sendTime": "2026-07-03T14:29:58.000Z",
    "type": "text",
    "text": { "body": "Olá! Quero saber mais." }
  }
}
Conforme o type, o corpo traz o bloco correspondente no lugar de text: image/video/document (com link, mimeType, caption), audio (com voice), location, contacts ou interactive (resposta de botão/lista). Mensagens vindas de anúncios click-to-WhatsApp incluem também o bloco referral com os dados da campanha (sourceId, headline, ctwaClid, ad, campaign).
Receber whatsapp.message.received também é o sinal de que a janela de 24 horas reabriu para aquele lead — a partir dali, mensagens de texto livre voltam a ser aceitas.

Verificando a assinatura

Cada entrega vem assinada nos headers svix-id, svix-timestamp e svix-signature (infraestrutura Svix — mesmo padrão usado por Clerk, Resend e outros). Verifique com a biblioteca da sua linguagem e o signing secret do endpoint:
import { Webhook } from "svix";

const wh = new Webhook(process.env.SUPERLEAD_WEBHOOK_SECRET);
// rawBody: corpo CRU da requisição (string), antes de qualquer JSON.parse
const event = wh.verify(rawBody, {
  "svix-id": req.headers["svix-id"],
  "svix-timestamp": req.headers["svix-timestamp"],
  "svix-signature": req.headers["svix-signature"],
});
Rejeite entregas com assinatura inválida. Sem a verificação, qualquer um que descubra sua URL pode forjar eventos.

Boas práticas

  • Idempotência: reentregas acontecem (é a garantia de “pelo menos uma vez”). Use o id do evento (evt_...) como chave de deduplicação no seu lado.
  • Ordem não garantida: um delivered pode chegar depois de um read. Use o timestamp do evento, não a ordem de chegada.
  • Webhook + polling: para fluxos críticos, combine os dois — webhook como caminho principal e GET /v1/messages/{id} como reconciliação periódica.