Webhook Overview
Webhooks are the primary way to receive real-time updates from the WhatsApp Business Platform. When users send messages, when message delivery status changes, or when account settings are updated, WhatsApp sends webhook notifications to your server.
What are Webhooks?
Webhooks are HTTP callbacks that WhatsApp sends to your server when events occur. Instead of constantly polling the API to check for new messages, webhooks push data to your application in real-time.
sequenceDiagram participant User participant WhatsApp participant Your Server
User->>WhatsApp: Sends message WhatsApp->>Your Server: POST /webhook (message event) Your Server->>WhatsApp: 200 OK Your Server->>WhatsApp: Send reply via API WhatsApp->>User: Delivers replyWhy Use Webhooks?
- Real-time: Receive notifications instantly when events occur
- Efficient: No need to poll the API constantly
- Complete: Get all message types, status updates, and account notifications
- Scalable: Handle high volumes of messages efficiently
Webhook Event Types
The SDK supports all WhatsApp webhook event types through the WebhookProcessor:
Message Events
Received when users send messages to your WhatsApp Business number:
- Text messages - Plain text messages
- Media messages - Images, videos, audio, documents, stickers
- Interactive messages - Button and list responses, Flow responses
- Location messages - Shared locations
- Contact messages - Shared contact cards
- Reaction messages - Message reactions (emoji)
- Order messages - Product orders from catalog
Status Events
Received when message delivery status changes:
sent- Message sent to WhatsApp serversdelivered- Message delivered to recipient deviceread- Message read by recipientfailed- Message delivery failed
Account Events
Received when your WhatsApp Business Account settings change:
- account_update - Account information changes
- account_review_update - Account review status changes
- account_alerts - Important account notifications
- business_capability_update - Business capabilities changes
Phone Number Events
Received when phone number settings change:
- phone_number_name_update - Display name changes
- phone_number_quality_update - Quality rating changes
Template Events
Received when message templates change:
- message_template_status_update - Template approval status
- template_category_update - Template category changes
- message_template_quality_update - Template quality rating
Other Events
- flows - WhatsApp Flows webhook events
- security - Security-related notifications
- history - Message history sync events
Webhook Payload Structure
All webhooks follow this structure:
interface WebhookPayload { object: 'whatsapp_business_account'; entry: Array<{ id: string; // Business Account ID changes: Array<{ value: { messaging_product: 'whatsapp'; metadata: { display_phone_number: string; phone_number_id: string; }; // Event-specific data contacts?: Array<...>; messages?: Array<...>; statuses?: Array<...>; }; field: 'messages' | 'account_update' | ...; }>; }>;}Webhook Security
WhatsApp secures webhooks in two ways:
1. Verification Token
When you first configure your webhook URL in the Meta Developer Portal, WhatsApp sends a GET request with a verification token. Your server must respond with the challenge value if the token matches.
// The SDK handles this automaticallyGET /webhook?hub.mode=subscribe&hub.verify_token=YOUR_TOKEN&hub.challenge=CHALLENGE
// Respond with: CHALLENGE (if token matches)2. Signature Verification
Each webhook POST request includes an X-Hub-Signature-256 header with a SHA256 HMAC signature. The SDK can verify this signature to ensure the request is authentic.
Setting Up Webhooks
To receive webhooks, you need to:
- Create a webhook endpoint - An HTTPS URL that can receive POST requests
- Configure in Meta Developer Portal:
- Go to your WhatsApp Business App
- Navigate to WhatsApp > Configuration
- Set your Callback URL and Verify Token
- Subscribe to webhook fields (messages, message_status, etc.)
- Implement webhook processing - Use the SDK to handle incoming webhooks
Webhook Processing Flow
import { WebhookProcessor } from 'meta-cloud-api';
// 1. Create processorconst processor = new WebhookProcessor({ accessToken: process.env.WHATSAPP_ACCESS_TOKEN, phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID, businessAcctId: process.env.WHATSAPP_BUSINESS_ACCOUNT_ID, webhookVerificationToken: process.env.WEBHOOK_VERIFICATION_TOKEN,});
// 2. Register handlersprocessor.onText(async (whatsapp, message) => { console.log('Received text:', message.text.body); await whatsapp.messages.text({ to: message.from, body: 'Echo: ' + message.text.body, });});
// 3. Process webhooksapp.post('/webhook', async (req, res) => { const result = await processor.processWebhook( new Request(req.url, { method: 'POST', headers: req.headers, body: JSON.stringify(req.body), }) ); res.status(result.status).send(result.body);});Best Practices
Response Time
WhatsApp expects a 200 OK response quickly. For long-running operations:
processor.onText(async (whatsapp, message) => { // Acknowledge immediately setImmediate(async () => { // Process in background await processMessage(message); });});Idempotency
WhatsApp may send the same webhook multiple times. Use message IDs to detect duplicates:
const processedMessages = new Set();
processor.onText(async (whatsapp, message) => { if (processedMessages.has(message.id)) { return; // Already processed }
processedMessages.add(message.id); // Process message...});Error Handling
Handle errors gracefully to avoid webhook delivery failures:
processor.onText(async (whatsapp, message) => { try { await processMessage(message); } catch (error) { console.error('Error processing message:', error); // Don't throw - still return 200 OK }});Rate Limiting
Be mindful of API rate limits when responding to webhooks:
import pLimit from 'p-limit';
const limit = pLimit(10); // Max 10 concurrent requests
processor.onText(async (whatsapp, message) => { await limit(() => whatsapp.messages.text({ to: message.from, body: 'Response', }));});Testing Webhooks Locally
During development, use ngrok or similar tools to expose your local server:
# Start your local servernpm run dev # Running on localhost:3000
# In another terminal, start ngrokngrok http 3000
# Use the ngrok URL in Meta Developer Portal# https://abc123.ngrok.io/webhook