WhatsApp

Webhook do WhatsApp: como configurar e validar (guia técnico)

Guia técnico do webhook da WhatsApp Cloud API: verificação com hub.challenge, assinatura X-Hub-Signature-256, estrutura do payload (messages e statuses) e boas práticas de produção.

Por Equipe SendKey
Webhook do WhatsApp: como configurar e validar (guia técnico)

O webhook do WhatsApp é a URL HTTPS do seu sistema que a Meta chama para entregar eventos da Cloud API: mensagens recebidas dos clientes e status de entrega (enviada, entregue, lida, falhou). A configuração tem duas partes: responder ao desafio de verificação (GET com hub.challenge) e validar a assinatura HMAC de cada notificação (header X-Hub-Signature-256). Quem usa uma plataforma como a Wizebot não precisa implementar isso — o webhook da Meta já vem tratado, e a plataforma expõe webhooks prontos para os seus sistemas.

Enviar mensagem pela Cloud API é a parte fácil. O que fecha o ciclo — receber respostas e saber o que foi entregue — é o webhook. Este guia cobre a implementação correta, incluindo as pegadinhas que não estão óbvias na documentação.

O que é o webhook do WhatsApp

Os requisitos são rígidos: URL pública, HTTPS com certificado válido (autoassinado não funciona) e resposta rápida. A configuração é feita no App Dashboard da Meta, assinando o campo messages.

Parte 1 — A verificação (GET)

Ao cadastrar a URL, a Meta faz uma única requisição GET com três parâmetros de query: hub.mode=subscribe, hub.verify_token (a string secreta que você definiu no painel) e hub.challenge (uma string aleatória).

Seu endpoint deve validar o token e devolver HTTP 200 com o valor puro de hub.challenge no corpo — sem JSON, sem aspas:

app.get("/webhook", (req, res) => {
  const { "hub.mode": mode, "hub.verify_token": token, "hub.challenge": challenge } = req.query;
  if (mode === "subscribe" && token === process.env.VERIFY_TOKEN) {
    return res.status(200).send(challenge);
  }
  return res.sendStatus(403);
});

Qualquer outra resposta e o cadastro falha — este é o primeiro ponto onde integrações travam.

Parte 2 — A assinatura (POST)

Toda notificação chega com o header X-Hub-Signature-256: um HMAC-SHA256 do corpo da requisição, usando o App Secret como chave. Validar é obrigatório em produção — sem isso, qualquer um que descubra sua URL pode injetar mensagens falsas.

As duas pegadinhas clássicas:

  1. Valide sobre o corpo bruto (raw body), antes de qualquer parse de JSON. A Meta assina o payload com caracteres especiais em unicode escapado — se você fizer parse e re-serializar, o hash nunca vai bater.
  2. Use comparação timing-safe (crypto.timingSafeEqual no Node, hmac.compare_digest no Python).

Parte 3 — O payload: messages vs. statuses

Tudo chega no mesmo envelope entry → changes → value:

{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "WABA_ID",
    "changes": [{
      "field": "messages",
      "value": {
        "metadata": { "phone_number_id": "..." },
        "messages": [{ "from": "5511...", "id": "wamid...", "type": "text", "text": { "body": "Oi!" } }]
      }
    }]
  }]
}

O que diferencia os eventos é qual array existe dentro de value:

Array em valueSignificadoCampos-chave
messagesMensagem recebida do clientefrom, type, corpo por tipo (text, image...)
statusesAtualização de mensagem enviadastatus (sent/delivered/read/failed), id (wamid)
errorsErro no nível da contacode, title, error_data

O wamid retornado no envio é a chave para correlacionar cada status. E atenção: falhas de entrega (como os erros 131026 e 131048) chegam como statuses com status: "failed" e um array errors — se você não tratar esse caso, suas mensagens somem silenciosamente.

Boas práticas de produção

  • Responda 200 imediatamente e processe depois (fila). Referência prática: menos de 5 segundos. Falhas consecutivas fazem a Meta reenviar com backoff e podem desabilitar a assinatura do webhook.
  • Não confie na ordem — eventos podem chegar fora de sequência (um read antes do delivered).
  • Trate duplicatas — a Meta reenvia notificações não confirmadas; use o wamid como chave de idempotência.
  • Registre o payload cru dos primeiros dias — é a única forma de depurar campos inesperados.

Precisa mesmo implementar tudo isso?

Se você está construindo um produto sobre a API da Meta, sim — e este guia mais o de integração cobrem o essencial. Mas se o objetivo é conectar o WhatsApp a sistemas de vendas e atendimento, há um atalho: a Wizebot já implementa e mantém o webhook da Meta (verificação, assinatura, retries, correlação de status) e expõe webhooks e API própria para os seus sistemas — você recebe eventos limpos e prontos, integrados a Hotmart, Shopify, Pipedrive, Google Sheets e mais de 50 plataformas.

Perguntas frequentes

Perguntas frequentes

O webhook do WhatsApp funciona em localhost?
Não diretamente — a Meta exige URL pública com HTTPS válido. Em desenvolvimento, usa-se um túnel (ngrok, Cloudflare Tunnel) apontando para a máquina local.
Por que meu webhook valida mas não recebe mensagens?
Causas mais comuns: esquecer de assinar o campo "messages" no App Dashboard, testar com o número errado (o webhook só recebe eventos dos números da WABA do app) ou o endpoint responder erro/demorar e a Meta pausar os envios.
Como sei se uma mensagem enviada falhou?
Pelo evento de status: a notificação chega com status "failed" e um array errors com o código do problema (ex.: 131026 para destinatário inalcançável, 131048 para limite de spam). Monitorar esses eventos é essencial em qualquer disparo em volume.
A validação da assinatura X-Hub-Signature-256 é obrigatória?
Tecnicamente a Meta não bloqueia quem não valida, mas sem ela seu endpoint aceita requisições forjadas por qualquer pessoa. Em produção, trate como obrigatória — e valide sempre sobre o corpo bruto da requisição.

Webhook bem feito é o que separa uma integração de WhatsApp confiável de uma que perde mensagens em silêncio. Se preferir pular a infraestrutura e ir direto para a operação, a Wizebot entrega a API oficial com todo esse encanamento pronto.