ZAP-API
PreçosCasos de UsoBlogDocsLogin
Começar grátis
  1. Blog
  2. Webhook WhatsApp seguro: HMAC, retry exponencial e DLQ
Tutorial

Webhook WhatsApp seguro: HMAC, retry exponencial e DLQ

Como usar webhook WhatsApp em produção com assinatura HMAC-SHA256, retry com backoff exponencial e Dead Letter Queue. Exemplos em Node.js.

30 de abril de 2026·11 min de leitura·Equipe Editorial ZAP-API
Webhook WhatsApp seguro: HMAC, retry exponencial e DLQ

Webhook é a espinha dorsal de qualquer integração WhatsApp séria — é por ele que sua aplicação recebe mensagens em tempo real, status de entrega, cliques em botão e mudanças de presença. Mas a maioria das APIs trata webhook como "POST e esquece": se cair, você perde o evento; se um atacante descobrir a URL, ele pode forjar mensagens; se sua API ficar 30s lenta, o provider desiste.

Na ZAP-API a plataforma de webhooks foi reconstruída em 2026 com 3 garantias que diferenciam um webhook "amador" de um webhook de produção: assinatura HMAC-SHA256, retry com backoff exponencial e Dead Letter Queue (DLQ) com replay one-click.

Por que isso importa

Um webhook sem essas três proteções é uma mina terrestre técnica:

  • Sem assinatura: qualquer pessoa que descobrir a URL pode disparar eventos forjados — cobranças falsas, mensagens fantasmas, scripts maliciosos.
  • Sem retry: se sua aplicação cair por 5 minutos durante um deploy, você perde todas as mensagens recebidas naquela janela. Para sempre.
  • Sem DLQ: quando um payload específico falhar (ex: bug no seu parser), você não tem como reprocessar depois de corrigir o código.

1. Assinatura HMAC-SHA256 — provando que veio da ZAP-API

Toda chamada de webhook envia o header X-ZapAPI-Signature-256 no formato sha256=<hex>: o HMAC-SHA256 do corpo bruto, calculado com o seu webhook secret. O secret é gerado na primeira vez que você configura a URL (PUT /v1/instances/:id/webhook), ou quando você envia "secret": true para trocá-lo, e aparece uma única vez na resposta — guarde-o. Você também pode enviar a sua própria chave (16 a 128 caracteres).

// Node.js / Express
const crypto = require('crypto');
const express = require('express');
const app = express();

const WEBHOOK_SECRET = process.env.ZAPAPI_WEBHOOK_SECRET;

// IMPORTANTE: use raw body para o HMAC bater
app.post(
  '/webhook/zap',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.headers['x-zapapi-signature-256'] || '';
    const expected = 'sha256=' + crypto
      .createHmac('sha256', WEBHOOK_SECRET)
      .update(req.body)
      .digest('hex');

    // timingSafeEqual evita timing attack (e exige o mesmo tamanho)
    const a = Buffer.from(signature);
    const b = Buffer.from(expected);
    if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
      return res.status(401).json({ error: 'invalid_signature' });
    }

    const event = JSON.parse(req.body.toString());
    console.log('Evento autenticado:', event.event, event.instanceId);

    // Responda 2xx em até 5s — erro ou demora entra em retry
    res.status(200).json({ ok: true });
  }
);

app.listen(3000);

Regra de ouro: nunca confie em payload de webhook sem validar a assinatura. Mesmo que a URL pareça "secreta", basta um log mal redactado, um header vazado em screenshot, ou um proxy mal configurado para que a URL seja descoberta.

2. Retry com exponential backoff + jitter

Quando sua aplicação responde com erro (5xx, 403, 404, 429…), não responde em 5 segundos ou redireciona, a ZAP-API reagenda a entrega. São 6 tentativas: a primeira imediata e as seguintes depois de 1min, 5min, 15min, 1h, 6h — cerca de 7 horas no total, com uma variação aleatória de até 20% em cada espera.

O jitter (variação aleatória) evita o thundering herd — se 1.000 webhooks falharem ao mesmo tempo (típico em outage parcial), o retry não bate todos juntos no mesmo segundo.

Por que espaçar em horas? Porque a causa mais comum de falha é o seu servidor estar fora do ar — um deploy que deu errado, um certificado vencido, um túnel de desenvolvimento que caiu. Tentativas em segundos acabariam antes de você perceber; espalhadas por 7 horas, dão tempo de consertar sem perder o evento.

Três respostas encerram na hora, sem retry: 400 (o payload não serve para o seu endpoint), 401 (seu endpoint recusou a autenticação) e 410 (você sinalizou que o endpoint não existe mais — nesse caso a URL é removida da instância).

3. Dead Letter Queue (DLQ) — segunda chance, no seu tempo

Depois das 6 tentativas falhas, a entrega fica guardada como "morta" — até 90 dias contados da criação do evento (entregas bem-sucedidas ficam 30 dias no histórico). Você pode reenviá-la quando quiser — útil quando:

  • Você acabou de fazer deploy do fix e quer reprocessar o que falhou.
  • Um cliente reclamou que "não recebeu a confirmação de pedido" — você acha a entrega, reenvia, problema resolvido sem ressincronizar do zero.
  • Você trocou a URL do webhook: o reenvio vai para a URL configurada agora.

Consultando e reenviando via API

// Histórico de entregas da instância (mais recentes primeiro)
GET /v1/instances/SEU_INSTANCE_ID/webhook/logs?limit=50&offset=0
Authorization: Bearer tk_seu_token

// Resposta
{
  "logs": [
    {
      "id": 48213,
      "event": "message.received",
      "url": "https://meu-app.com/webhook",
      "statusCode": 500,
      "errorMessage": "Request failed with status code 500",
      "delivered": false,
      "attempt": 6,
      "maxAttempts": 6,
      "nextRetryAt": null,
      "createdAt": "2026-04-30T12:34:56Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

// Reenviar uma entrega que esgotou as tentativas (ou falhou)
POST /v1/instances/SEU_INSTANCE_ID/webhook/deliveries/48213/replay
Authorization: Bearer tk_seu_token

O reenvio reaproveita a mesma entrega e o mesmo X-Zap-Event-Id, e recomeça as tentativas. Respostas possíveis: 409 WEBHOOK_PAUSED (reative o webhook no painel primeiro), 409 NO_WEBHOOK_URL (configure uma URL — acontece depois de um 410) e 422 para entrega já entregue ou com menos de 5 minutos e sem nova tentativa agendada.

Padrões de implementação que evitam dor de cabeça

Idempotência: cada evento traz um X-Zap-Event-Id único

Mesmo com retry, a ZAP-API pode entregar o mesmo evento mais de uma vez (ex: sua aplicação respondeu 200 mas a conexão caiu antes). O header X-Zap-Event-Id é o mesmo em todas as tentativas e no reenvio. Salve-o e ignore duplicatas:

const eventId = req.headers['x-zap-event-id'];
const seen = await db.events.findOne({ where: { eventId } });
if (seen) {
  return res.status(200).json({ ok: true, duplicate: true });
}
await db.events.create({ eventId, payload: event });
// ...processar...

Acknowledge primeiro, processe depois

Não rode lógica pesada antes de retornar 200. Coloque o evento em uma fila interna (BullMQ, Redis Streams, SQS) e responda imediatamente:

app.post('/webhook/zap', async (req, res) => {
  // 1. Valida HMAC (rápido)
  if (!validSignature(req)) return res.status(401).end();

  // 2. Enfileira (rápido)
  await queue.add('process-webhook', JSON.parse(req.body));

  // 3. Responde (rápido)
  res.status(200).json({ ok: true });
});

Esse padrão derruba seu p99 de webhook de "1500ms quando o banco está lento" para "8ms sempre".

Eventos disponíveis

A ZAP-API entrega 21 tipos de evento via webhook:

  • message.received, message.sent, message.status, message.read, message.reaction, message.edited, message.deleted
  • instance.connected, instance.disconnected, instance.qrcode, instance.test
  • group.join, group.leave, group.update
  • contact.update, presence.update
  • call.received, call.rejected
  • status.viewed, label.update, newsletter.update

Você escolhe quais quer receber em cada instância, no painel ou via PUT /v1/instances/:id/webhook.

FAQ

  • Posso ter mais de uma URL de webhook por instância?
    Não — cada instância tem uma URL. Para mandar eventos a vários sistemas, aponte para um endpoint seu que faz o fan-out. Você pode filtrar quais eventos recebe.
  • O HMAC é obrigatório?
    O header é sempre enviado. Validar do seu lado é opcional, mas fortemente recomendado em produção.
  • O que acontece se eu não habilitar webhook?
    Você pode usar polling (GET /v1/instances/:id/messages), mas perde latência (5-30s) e gasta mais quota de API.
  • Há rate limit no webhook?
    Não há rate limit de saída — entregamos tudo. O limite é só na sua aplicação aguentar receber.
  • Quanto tempo a DLQ retém entregas?
    Entregas que não chegaram: até 90 dias, contados da criação do evento. Entregas bem-sucedidas: 30 dias. Depois disso são apagadas.

Criar conta e configurar webhooks com HMAC, retry e DLQ — trial 7 dias, sem cartão.

Experimente a ZAP-API gratuitamente

7 dias de trial sem precisar de cartão. A partir de R$29/mês*.

Criar instância grátis
EE
Equipe Editorial ZAP-APIRevisão técnica

Desenvolvedores e especialistas em integrações WhatsApp. Todo conteúdo passa por revisão técnica para garantir precisão e aplicabilidade.

Ver perfil completoDocumentaçãoTrial grátis

Leia também

Tutorial · 29 de jun. de 2026 · 8 min

Como integrar Webhook do WhatsApp em Node.js

Guia completo para integrar webhooks WhatsApp em Node.js. Passo a passo com código pronto. Comece grátis na ZAP API.

Tutorial · 06 de jun. de 2026 · 10 min

Webhook WhatsApp: receba mensagens em tempo real com Node.js, Python e PHP (2026)

Configure um endpoint que recebe cada mensagem do WhatsApp em tempo real, valida a assinatura HMAC-SHA256 e processa com retry automático. Exemplos completos nas 3 linguagens.

Tutorial · 05 de mar. de 2026 · 10 min

Webhook WhatsApp: Integração e Configuração Fácil

Descubra como configurar webhook WhatsApp e receba mensagens em tempo real. Integre agora com ZAP-API! Cadastre-se grátis.

Tutorial · 17 de mai. de 2026 · 12 min

Console de webhooks com replay: debug em produção sem logs manuais

Use o console de webhooks da ZAP-API para inspecionar entregas, ver payloads completos, re-enviar eventos com falha e diagnosticar integrações sem acesso ao servidor.

Tópicos:Chatbots com IAE-commerceAPI WhatsApp

Explore também

API WhatsApp grátisTeste 7 dias, sem cartãoAutomação WhatsAppAutomatize via REST APIAPI não oficialSem aprovação da MetaCasos de usoWhatsApp API por segmentoComparativoZAP-API vs alternativasPreçosPlanos e o que está inclusoGlossárioTermos técnicos de WhatsApp API
ZAP-API

API REST para WhatsApp com webhooks assinados, Meta Pixel/CAPI e compliance LGPD. Sem aprovação da Meta.

Status operacional🇧🇷 Feito no Brasil

Produto

  • Preços
  • Casos de uso
  • Automação WhatsApp
  • API não oficial
  • Comparativo
  • API WhatsApp grátis
  • Dashboard

Recursos

  • Documentação
  • Blog
  • Glossário
  • RSS Feed

Empresa

  • Sobre
  • Imprensa
  • Termos de uso
  • Privacidade
  • Criar conta
  • Login

Contato

  • [email protected]
  • [email protected]
  • Resposta em até 24h úteis
© 2026 ZAP-API — Todos os direitos reservados·CNPJ 42.130.949/0001-56·Termos·Privacidade

Desenvolvido por PreviusIA