Documentação

Webhooks

Cadastre um endpoint HTTPS com POST /webhooks e os eventos que quer. Cada evento vira uma entrega: um POST com corpo JSON e três headers. O segredo de assinatura é devolvido uma vez, na criação. A URL precisa ser https e apontar para um host público: endereço de rede privada, loopback e link-local são recusados, e para testar na sua máquina use um túnel.

Eventos

  • message.received: um cliente mandou mensagem. Traz wamid, from, phoneNumberId, type, text, os campos de mídia, replyPayload, flowResponse, order e o messageId da Zaiped para GET /media.
  • message.status: uma mensagem sua foi entregue, lida ou falhou, com error e pricing.
  • template.status: o veredito da Meta sobre um modelo.
  • number.update: mudanças de qualidade, limite de envio ou nome de exibição.
  • account.notice: avisos da WABA, inclusive acesso perdido.
  • call.event: eventos e status de chamada de voz.

O corpo

{
  "id": "YOUR_DELIVERY_ID",
  "event": "message.received",
  "createdAt": 1757160000000,
  "data": { "wamid": "wamid.HBg...", "from": "+5511999999999", "type": "text", "text": "Oi", "messageId": "..." }
}

Headers e assinatura

  • X-Zaiped-Event: o nome do evento.
  • X-Zaiped-Delivery: o id da entrega, o mesmo em todas as tentativas dela. Use para deduplicar.
  • X-Zaiped-Signature: t=TIMESTAMP,v1=HEX, onde v1 é HMAC-SHA256(secret, "TIMESTAMP.CORPO_CRU").
// Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, header, secret) {
  const [t, v1] = header.split(",").map((part) => part.slice(part.indexOf("=") + 1));
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Uma entrega por evento

A Meta reentrega o mesmo evento quando não tem certeza de que o recebemos, e nós absorvemos isso: um evento de origem gera UMA entrega por endpoint, com um X-Zaiped-Delivery só. O que se repete é a tentativa da MESMA entrega, quando o seu endpoint não responde 2xx, e aí o id é o mesmo. Guarde o id que já processou e ignore repetição: é a rede que sobra para o caso raro de um evento sem identidade estável, que preferimos entregar duas vezes a engolir.

Retentativa

Responda 2xx rápido. Qualquer outra coisa, ou um timeout de dez segundos, agenda uma retentativa depois de um minuto, depois cinco, trinta, duas horas e doze horas. São seis tentativas ao todo (a primeira mais as cinco esperas); depois delas a entrega é marcada como failed e fica no registro por trinta dias. GET /webhooks/{webhookId}/deliveries lista as recentes; POST .../test manda um evento de teste.