Webhooks provide real-time notifications for WhatsApp events. Receive instant updates when messages are delivered, read, or when template status changes occur.
When specific events occur in your WhatsApp account, TheQuickAssist sends a POST request to your configured webhook URL with event details. This enables real-time integration with your backend systems.
Message sent, delivered, or read
Webhook payload sent to your URL
Your server handles the notification
Triggered when a customer sends a text, image, location, contact card, audio, interactive response, or click button to your WhatsApp Business number.
Triggered when a template or session message status changes (sent, delivered, read, or failed).
Forwarded for any other webhook payloads sent by Meta that belong to your configured phone number (e.g. quick reply button clicks).
All webhook notifications are forwarded to your server using the exact raw Meta WABA payload format:
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WABA_BUSINESS_ACCOUNT_ID",
"changes": [
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "16505553333",
"phone_number_id": "1234567890"
},
"contacts": [
{
"profile": { "name": "Customer Name" },
"wa_id": "1234567890"
}
],
"messages": [
{
"from": "1234567890",
"id": "wamid.HBgLMTIx...",
"timestamp": "1718520000",
"text": { "body": "Hey there!" },
"type": "text"
}
]
}
}
]
}
]
}Set up a public HTTPS endpoint on your server that can receive POST requests. The endpoint must return a 2xx status code to acknowledge receipt.
In your chatbot dashboard, navigate to Settings → API Keys → Webhooks. Enter your webhook URL and optionally save a Webhook Secret.
https://yourdomain.com/webhooks/whatsappVerify webhook signatures to ensure requests are authentic and from TheQuickAssist:
const signature = req.headers['x-webhook-signature'];
if (!signature) return res.status(401).send('Missing signature');
// Extract hash from signature format (sha256=hash)
const parts = signature.split('=');
const signatureHash = parts.length > 1 ? parts[1] : parts[0];
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
const matches = crypto.timingSafeEqual(
Buffer.from(signatureHash, 'hex'),
Buffer.from(expected, 'hex')
);
if (!matches) {
return res.status(401).send('Invalid signature');
}