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:

  1. Vá para Meta Business Suite
  2. Configurações > WhatsApp > Configuração da API
  3. 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:

  1. Vá para seu App > Webhooks
  2. Em "WhatsApp Business Account", clique em "Subscribe"
  3. 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:

  1. Número não vinculado: O número WhatsApp Business precisa estar vinculado ao seu App
  2. App em modo desenvolvimento: Precisa estar em modo "Live"
  3. 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

  1. Vá para Meta for Developers
  2. Seu App > Webhooks
  3. Clique em "Test" ao lado de messages
  4. 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:

  1. App não inscrito no WABA
  2. Resposta lenta (não responde 200 rápido)
  3. Campos não inscritos
  4. 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.

.