Webhooks do WhatsApp: como receber mensagens no seu sistema
·5 min de leitura
Resposta rápida
O webhook é a URL pública onde a Meta entrega tudo que acontece no seu número: mensagem recebida, status de entrega e leitura. Você a cadastra no painel do app, responde ao desafio de verificação com o hub.challenge e passa a receber POSTs em JSON. Responda 200 imediatamente e processe depois — a Meta reenvia o que não for confirmado rápido.
Enviar pela API oficial é uma requisição HTTP e resolve em dez minutos. Receber é onde o projeto realmente começa — e é a parte que surpreende quem imaginava algo mais simples.
Não existe “consultar mensagens novas”. A Meta empurra os eventos para você, e isso significa um servidor público, sempre no ar.
Como funciona
- 1
Cliente manda mensagem
Para o seu número da API
- 2
Meta monta o evento
JSON com remetente, conteúdo e id
- 3
POST na sua URL
O webhook que você cadastrou
- 4
Você responde 200
Rápido. O processamento vem depois
Configuração
- 1
Tenha uma URL pública com HTTPS
Precisa ser acessível pela internet, com certificado válido. Em desenvolvimento, um túnel resolve; em produção, é um servidor de verdade.
- 2
Implemente a verificação (GET)
Ao cadastrar a URL, a Meta faz um GET com
hub.mode,hub.verify_tokenehub.challenge. Confira se o token bate com o seu e devolva ohub.challengecomo texto puro. É aqui que quase todo mundo trava na primeira vez. - 3
Implemente o recebimento (POST)
Os eventos chegam como POST em JSON. Responda 200 imediatamente, antes de processar — a Meta reenvia o que demora a ser confirmado.
- 4
Assine os campos que interessam
No painel, escolha os campos do webhook.
messagescobre mensagens recebidas e status de entrega, e é o essencial.
// verificação — a Meta chama uma vez, ao cadastrar a URL
app.get("/webhook", (req, res) => {
const modo = req.query["hub.mode"];
const token = req.query["hub.verify_token"];
if (modo === "subscribe" && token === process.env.VERIFY_TOKEN) {
return res.status(200).send(req.query["hub.challenge"]);
}
res.sendStatus(403);
});
// recebimento — responda 200 antes de processar
app.post("/webhook", (req, res) => {
res.sendStatus(200);
enfileirar(req.body);
});res.sendStatus(200) vem antes do processamento de propósito: qualquer demora vira reenvio.O que a Meta manda
O corpo é aninhado e o dado útil está fundo. Vale conhecer o formato antes de escrever o parser:
{
"entry": [{
"changes": [{
"value": {
"messaging_product": "whatsapp",
"contacts": [{ "wa_id": "558599999999", "profile": { "name": "Marina" } }],
"messages": [{
"from": "558599999999",
"id": "wamid.HBgNNTU...",
"timestamp": "1789567890",
"type": "text",
"text": { "body": "Quero um orçamento" }
}]
},
"field": "messages"
}]
}]
}wa_id: 558599999999, sem o nono dígito. Para DDDs fora do Sudeste isso é a regra, não a exceção.Os tipos de evento
| Chave | O que é | Uso |
|---|---|---|
messages | Mensagem recebida do cliente | Abre a janela de 24h e alimenta o atendimento |
statuses | sent, delivered, read, failed | Confirmação de entrega e diagnóstico |
errors | Falha no envio | Log e alerta |
type: interactive | Toque em botão ou item de lista | Conta como mensagem do cliente |
type: image / audio / document | Mídia recebida | Vem um id; o arquivo é baixado à parte |
Os quatro problemas que todo mundo encontra
- 1Mensagem repetida. A Meta reenvia quando não recebe 200 rápido. A correção não é acelerar o processamento — é guardar o `id` da mensagem e ignorar o que já foi visto. Sem isso, o cliente recebe a mesma resposta três vezes.
- 2Ordem trocada. Os eventos não chegam necessariamente na ordem em que aconteceram. Use o
timestamp, não a ordem de chegada. - 3Endpoint fora do ar. A Meta tenta de novo por um tempo e depois desiste — e pode desativar a assinatura se o erro persistir. Monitore o webhook como serviço crítico, porque é isso que ele é.
- 4Assinatura não validada. Sem validar, qualquer um que descubra sua URL injeta eventos falsos no seu sistema.
Validar a assinatura
Todo POST vem com o cabeçalho X-Hub-Signature-256, que é um HMAC SHA-256 do corpo cru usando o segredo do seu app.
import crypto from "node:crypto";
function assinaturaValida(corpoCru, cabecalho) {
const esperado =
"sha256=" +
crypto.createHmac("sha256", process.env.APP_SECRET)
.update(corpoCru)
.digest("hex");
// timingSafeEqual, e não ===: comparação comum vaza o tempo de acerto
return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(cabecalho));
}Guardar o corpo cru antes do parser de JSON é o detalhe que faz a validação funcionar — e a causa da maioria dos “minha assinatura nunca confere”.
Webhook e a janela de 24 horas
Todo evento em messages reinicia a janela daquele cliente. Vale registrar o horário: é o que permite saber se ainda dá para responder com texto livre ou se já é caso de template.
- Guarde
timestampda última mensagem recebida por contato. - Antes de enviar, compare com agora: menos de 24h, texto livre; mais, template.
- Toque em botão também conta e reabre a janela.
- O mecanismo completo está em janela de 24 horas.
Quem constrói produto para terceiros e precisa conectar a conta de cada cliente deve olhar o Embedded Signup, que registra a assinatura de webhook automaticamente ao fim do fluxo.
Antes de construir tudo isso
Webhook exige servidor no ar, fila, deduplicação, validação de assinatura e monitoramento. É trabalho de infraestrutura contínuo, não de uma semana.
Existe um meio-termo: ferramentas de automação visual recebem o webhook por você e entregam a URL pronta, o que resolve a parte chata sem escrever servidor — o caminho está em integrar o WhatsApp com n8n, Make e Zapier.
Vale conferir se você precisa mesmo. Para atendimento de dezenas de conversas por dia, o WhatsApp Business gratuito entrega o mesmo resultado sem nada disso. A API compensa quando a mensagem precisa sair de um sistema ou quando o volume de atendimento passou do que quatro pessoas dão conta.
Perguntas frequentes
Dá para usar a API do WhatsApp sem webhook?
Dá para enviar, mas não para receber. Não existe endpoint de consulta de mensagens novas: a entrega é sempre por push. Sem webhook, é um canal de mão única.
Por que estou recebendo a mesma mensagem várias vezes?
Porque seu endpoint não respondeu 200 rápido o suficiente. Responda antes de processar e guarde o id da mensagem para ignorar repetições.
Posso usar HTTP em vez de HTTPS?
Não. A Meta exige HTTPS com certificado válido, inclusive na verificação inicial.
O que acontece se meu servidor cair?
A Meta tenta reenviar por um período e depois desiste. Se as falhas persistirem, a assinatura do webhook pode ser desativada e você para de receber tudo.
As fotos e áudios vêm no webhook?
Não. Vem o identificador da mídia, e o arquivo é baixado numa segunda requisição autenticada. Os arquivos ficam disponíveis por tempo limitado — baixe assim que chegar.
Um webhook serve para vários números?
Serve. Os eventos trazem o identificador do número que recebeu, e o mesmo endpoint atende a conta comercial inteira.
Resumo
- Webhook é a única forma de receber mensagens: exige URL pública com HTTPS.
- Responda ao GET de verificação devolvendo o
hub.challengecomo texto puro. - Responda 200 antes de processar e deduplique pelo id da mensagem.
- Valide a assinatura sobre o corpo cru, com comparação de tempo constante.
- No Brasil, o
wa_idcostuma vir sem o nono dígito — use-o como identificador.
Leia também
API oficial do WhatsApp (Cloud API): guia para começar
O que é a API oficial do WhatsApp, quando ela vale a pena, o que a Meta exige, como enviar a primeira mensagem e os limites que derrubam projeto no começo.
1 de agosto de 2026 · 8 min
Janela de 24 horas do WhatsApp: o que é e como usar
A regra que define quando você pode escrever livremente e quando só sai template aprovado. Como a janela abre, quando fecha e as táticas para não perder o cliente.
4 de julho de 2026 · 5 min
Templates de mensagem do WhatsApp: criar e ser aprovado
Como escrever um template que a Meta aprova de primeira, as regras de variável, os motivos de recusa mais comuns e como não cair na categoria mais cara.
31 de julho de 2026 · 6 min