Webhooks
Webhooks entregam eventos do WhatsApp ao seu servidor em tempo real. Em vez de ficar consultando a API, a ZapDev faz um POST na sua URL sempre que algo acontece, com entrega assíncrona, assinada e com retry.
Como funciona
Seção intitulada “Como funciona”Você registra uma URL pública HTTPS na instância. A cada evento, mensagem recebida, status de entrega, conexão alterada, a ZapDev envia um POST com corpo JSON. Sua aplicação responde 2xx para confirmar.
Eventos disponíveis
Seção intitulada “Eventos disponíveis”Todo payload traz event, instanceId, timestamp e data.
| Evento | Quando |
|---|---|
message.received |
Mensagem recebida na instância |
message.sent |
Mensagem enviada |
message.delivered |
Entregue ao destinatário |
message.read |
Lida pelo destinatário |
message.failed |
Falha no envio |
instance.connected |
Instância conectada |
instance.disconnected |
Instância desconectada |
instance.qr_updated |
Novo QR Code disponível |
Payload · message.received
{ "event": "message.received", "instanceId": "ins_8f2a91", "timestamp": "2026-07-11T14:35:11Z", "data": { "messageId": "msg_9Kp2", "from": "5511988887777", "pushName": "Marina Costa", "type": "text", "text": "Oi! Qual o horário de vocês?" }}message.received por tipo
Seção intitulada “message.received por tipo”O campo type indica o que chegou: text, image, video, audio, document, sticker, location, reaction ou contact. Mensagens de mídia trazem um objeto media (com mimetype, fileName e, se o webhook estiver com base64 ligado, o conteúdo em base64); a legenda vem em text.
{ "event": "message.received", "instanceId": "ins_8f2a91", "data": { "messageId": "msg_9Kp2", "from": "5511988887777", "type": "image", "text": "Chegou o catálogo", "media": { "mimetype": "image/jpeg", "base64": "..." } }}Validando a assinatura
Seção intitulada “Validando a assinatura”Toda requisição traz o header X-ZapDev-Signature: sha256=<hash>, um HMAC-SHA256 do corpo bruto, assinado com o segredo do webhook da instância. Valide-o para garantir que o evento veio da ZapDev.
Validação
import crypto from 'node:crypto'
function verify(rawBody, signature, secret) { const hmac = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex')
return crypto.timingSafeEqual( Buffer.from(hmac), Buffer.from(signature), )}Política de retry
Seção intitulada “Política de retry”Se sua URL não responder 2xx, a ZapDev reenvia com backoff:
- Até 5 tentativas.
- Intervalos:
1s,5s,30s,2min,10min. - Sucesso em
2xx; falha em4xx(sem retry, exceto408e429) ou5xx.