Webhook WhatsApp API Não Recebe Mensagens: Guia Completo de Troubleshooting
Como resolver quando seu webhook da WhatsApp Business API não está recebendo mensagens. Guia passo a passo com soluções.
O Problema
Você configurou seu webhook no Meta for Developers, o teste de verificação passou, mas quando envia mensagens reais para seu número WhatsApp Business... nada acontece. Zero execuções. Este é um dos problemas mais frustrantes da WhatsApp Business API.
Checklist de Diagnóstico
Antes de tudo, verifique estes pontos:
- [ ] Webhook URL está acessível publicamente (não localhost)
- [ ] Certificado SSL válido (HTTPS obrigatório)
- [ ] Verification Token está correto em ambos os lados
- [ ] App está inscrito para receber mensagens do WABA
- [ ] Número WhatsApp está vinculado ao App
- [ ] Endpoint responde corretamente ao GET e POST
Causa 1: Webhook não está inscrito no WABA
Este é o erro mais comum. Seu app precisa estar inscrito para receber mensagens do seu WhatsApp Business Account.
Solução
// Inscrever o app no WABA via API
const response = await fetch(
`https://graph.facebook.com/v18.0/${wabaId}/subscribed_apps`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
}
}
);
const data = await response.json();
console.log('Inscrição:', data);
// Esperado: { "success": true }
Ou faça manualmente:
- Vá para Meta Business Suite
- Configurações > WhatsApp > Configuração da API
- Vincule seu App
Causa 2: Verificação GET funciona, POST não
O webhook responde ao desafio de verificação (GET), mas não processa mensagens (POST).
Solução
Seu endpoint precisa tratar ambos os métodos:
// Express.js exemplo
app.get('/webhook', (req, res) => {
// Verificação do webhook
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.VERIFY_TOKEN) {
console.log('Webhook verificado!');
res.status(200).send(challenge);
} else {
res.sendStatus(403);
}
});
app.post('/webhook', (req, res) => {
// IMPORTANTE: Responda 200 IMEDIATAMENTE
res.sendStatus(200);
// Processe a mensagem de forma assíncrona
const body = req.body;
if (body.object === 'whatsapp_business_account') {
body.entry?.forEach(entry => {
entry.changes?.forEach(change => {
if (change.field === 'messages') {
const message = change.value.messages?.[0];
if (message) {
processMessage(message);
}
}
});
});
}
});
async function processMessage(message) {
console.log('Mensagem recebida:', message);
// Sua lógica aqui
}
Causa 3: Webhook não responde 200 rápido o suficiente
A Meta espera uma resposta 200 em até 20 segundos. Se demorar mais, ela considera falha e pode parar de enviar.
Solução
Responda 200 imediatamente e processe depois:
app.post('/webhook', async (req, res) => {
// 1. Responda PRIMEIRO
res.sendStatus(200);
// 2. Processe DEPOIS (assíncrono)
try {
await processWebhookPayload(req.body);
} catch (error) {
console.error('Erro processando webhook:', error);
// Não afeta a resposta já enviada
}
});
Ou use uma fila:
import { Queue } from 'bullmq';
const webhookQueue = new Queue('whatsapp-webhooks');
app.post('/webhook', async (req, res) => {
res.sendStatus(200);
// Adiciona na fila para processamento
await webhookQueue.add('process-message', req.body);
});
Causa 4: Campos não inscritos
Você precisa se inscrever nos campos corretos de webhook.
Solução
No Meta for Developers:
- Vá para seu App > Webhooks
- Em "WhatsApp Business Account", clique em "Subscribe"
- Marque o campo messages
Via API:
// Verificar inscrições atuais
const response = await fetch(
`https://graph.facebook.com/v18.0/${appId}/subscriptions`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
);
// Inscrever no campo messages
await fetch(
`https://graph.facebook.com/v18.0/${appId}/subscriptions`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
object: 'whatsapp_business_account',
callback_url: 'https://seudominio.com/webhook',
verify_token: process.env.VERIFY_TOKEN,
fields: ['messages']
})
}
);
Causa 5: Teste da Meta funciona, mensagens reais não
O botão "Send Test Message" no painel da Meta funciona, mas mensagens enviadas pelo WhatsApp não chegam.
Possíveis causas:
- Número não vinculado: O número WhatsApp Business precisa estar vinculado ao seu App
- App em modo desenvolvimento: Precisa estar em modo "Live"
- Permissões faltando: Verifique se tem
whatsapp_business_messaging
Solução
// Verificar vinculação do número
const response = await fetch(
`https://graph.facebook.com/v18.0/${phoneNumberId}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
);
const data = await response.json();
console.log('Número vinculado:', data);
Causa 6: Firewall ou proxy bloqueando
Seu servidor pode estar bloqueando requisições da Meta.
Solução
Libere os IPs da Meta no firewall. A Meta publica a lista em: https://developers.facebook.com/docs/sharing/webmasters/crawler
Ou verifique os headers:
app.post('/webhook', (req, res) => {
console.log('Headers recebidos:', req.headers);
console.log('IP de origem:', req.ip);
console.log('Body:', JSON.stringify(req.body, null, 2));
res.sendStatus(200);
});
Debugging: Ver eventos no Meta
- Vá para Meta for Developers
- Seu App > Webhooks
- Clique em "Test" ao lado de messages
- Veja a aba "Recent Deliveries" para logs de tentativas
Template de Webhook Completo
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.json());
const VERIFY_TOKEN = process.env.VERIFY_TOKEN;
const APP_SECRET = process.env.APP_SECRET;
// Verificar assinatura (segurança)
function verifySignature(req) {
const signature = req.headers['x-hub-signature-256'];
if (!signature) return false;
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', APP_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// GET - Verificação
app.get('/webhook', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === VERIFY_TOKEN) {
console.log('✅ Webhook verificado');
return res.status(200).send(challenge);
}
console.log('❌ Verificação falhou');
res.sendStatus(403);
});
// POST - Mensagens
app.post('/webhook', (req, res) => {
// Verificar assinatura
if (!verifySignature(req)) {
console.log('❌ Assinatura inválida');
return res.sendStatus(401);
}
// Responder imediatamente
res.sendStatus(200);
// Log para debug
console.log('📨 Webhook recebido:', JSON.stringify(req.body, null, 2));
// Processar
const { entry } = req.body;
entry?.forEach(e => {
e.changes?.forEach(change => {
if (change.field === 'messages') {
const messages = change.value.messages || [];
messages.forEach(msg => {
console.log(`💬 Mensagem de ${msg.from}: ${msg.text?.body || '[mídia]'}`);
});
}
});
});
});
app.listen(3000, () => {
console.log('🚀 Webhook server rodando na porta 3000');
});
Conclusão
Problemas de webhook geralmente são:
- App não inscrito no WABA
- Resposta lenta (não responde 200 rápido)
- Campos não inscritos
- Problemas de rede/firewall
Use os logs da Meta para diagnosticar e sempre responda 200 imediatamente.
Precisa de ajuda configurando webhooks? Entre em contato para consultoria.