WhatsApp API Webhook Not Receiving Messages: Complete Troubleshooting Guide
How to fix when your WhatsApp Business API webhook is not receiving messages. Step-by-step guide with solutions.
The Problem
You configured your webhook in Meta for Developers, the verification test passed, but when you send real messages to your WhatsApp Business number... nothing happens. Zero executions. This is one of the most frustrating problems with the WhatsApp Business API.
Diagnostic Checklist
Before anything, check these points:
- [ ] Webhook URL is publicly accessible (not localhost)
- [ ] Valid SSL certificate (HTTPS required)
- [ ] Verification Token is correct on both sides
- [ ] App is subscribed to receive messages from WABA
- [ ] WhatsApp number is linked to the App
- [ ] Endpoint responds correctly to GET and POST
Cause 1: Webhook is not subscribed to WABA
This is the most common error. Your app needs to be subscribed to receive messages from your WhatsApp Business Account.
Solution
// Subscribe app to 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('Subscription:', data);
// Expected: { "success": true }
Or do it manually:
- Go to Meta Business Suite
- Settings > WhatsApp > API Configuration
- Link your App
Cause 2: GET verification works, POST doesn't
The webhook responds to the verification challenge (GET), but doesn't process messages (POST).
Solution
Your endpoint needs to handle both methods:
// Express.js example
app.get('/webhook', (req, res) => {
// Webhook verification
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 verified!');
res.status(200).send(challenge);
} else {
res.sendStatus(403);
}
});
app.post('/webhook', (req, res) => {
// IMPORTANT: Respond 200 IMMEDIATELY
res.sendStatus(200);
// Process the message asynchronously
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('Message received:', message);
// Your logic here
}
Cause 3: Webhook doesn't respond 200 fast enough
Meta expects a 200 response within 20 seconds. If it takes longer, it considers it a failure and may stop sending.
Solution
Respond 200 immediately and process later:
app.post('/webhook', async (req, res) => {
// 1. Respond FIRST
res.sendStatus(200);
// 2. Process AFTER (async)
try {
await processWebhookPayload(req.body);
} catch (error) {
console.error('Error processing webhook:', error);
// Doesn't affect the already sent response
}
});
Or use a queue:
import { Queue } from 'bullmq';
const webhookQueue = new Queue('whatsapp-webhooks');
app.post('/webhook', async (req, res) => {
res.sendStatus(200);
// Add to queue for processing
await webhookQueue.add('process-message', req.body);
});
Cause 4: Fields not subscribed
You need to subscribe to the correct webhook fields.
Solution
In Meta for Developers:
- Go to your App > Webhooks
- Under "WhatsApp Business Account", click "Subscribe"
- Check the messages field
Via API:
// Check current subscriptions
const response = await fetch(
`https://graph.facebook.com/v18.0/${appId}/subscriptions`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
);
// Subscribe to messages field
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://yourdomain.com/webhook',
verify_token: process.env.VERIFY_TOKEN,
fields: ['messages']
})
}
);
Cause 5: Meta test works, real messages don't
The "Send Test Message" button in Meta's panel works, but messages sent via WhatsApp don't arrive.
Possible causes:
- Number not linked: The WhatsApp Business number needs to be linked to your App
- App in development mode: Needs to be in "Live" mode
- Missing permissions: Check if you have
whatsapp_business_messaging
Complete Webhook Template
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;
// Verify signature (security)
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 - Verification
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 verified');
return res.status(200).send(challenge);
}
console.log('❌ Verification failed');
res.sendStatus(403);
});
// POST - Messages
app.post('/webhook', (req, res) => {
// Verify signature
if (!verifySignature(req)) {
console.log('❌ Invalid signature');
return res.sendStatus(401);
}
// Respond immediately
res.sendStatus(200);
// Log for debug
console.log('📨 Webhook received:', JSON.stringify(req.body, null, 2));
// Process
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(`💬 Message from ${msg.from}: ${msg.text?.body || '[media]'}`);
});
}
});
});
});
app.listen(3000, () => {
console.log('🚀 Webhook server running on port 3000');
});
Conclusion
Webhook problems are usually:
- App not subscribed to WABA
- Slow response (doesn't respond 200 fast enough)
- Fields not subscribed
- Network/firewall issues
Use Meta's logs to diagnose and always respond 200 immediately.
Need help setting up webhooks? Contact me for consulting.