Webhooks
Complete guide to webhook events and handling
Webhooks
Receive real-time notifications about events in your WhatsApp Business account via webhooks.
Overview
Webhooks allow you to receive instant notifications when events occur in your system, such as:
- New messages received
- Message status updates (sent, delivered, read)
- Conversation events
- Order updates
- And more...
Setting Up Webhooks
1. Configure Webhook URL
Set your webhook endpoint URL in the dashboard:
https://your-domain.com/webhooks/awalchat
2. Verify Webhook
When you set up a webhook, we'll send a verification request:
POST /webhooks/awalchat
Content-Type: application/json
{
"type": "verification",
"challenge": "random_string_here"
}Response Required:
HTTP/1.1 200 OK
Content-Type: application/json
{
"challenge": "random_string_here"
}Security
Always verify the webhook signature before processing events. See Webhook Security below.
Webhook Events
Message Events
message.received
Triggered when a new message is received.
{
"event": "message.received",
"timestamp": "2024-01-20T10:30:00Z",
"data": {
"message_id": "wamid.HBgMOTY2NTAwMDAwMDAwFQIAERgS...",
"conversation_id": 123,
"from": "96650000000",
"to": "96650000001",
"type": "text",
"body": "Hello, I need help",
"timestamp": "2024-01-20T10:30:00Z"
}
}message.status.updated
Triggered when message status changes (sent, delivered, read).
{
"event": "message.status.updated",
"timestamp": "2024-01-20T10:31:00Z",
"data": {
"message_id": "wamid.HBgMOTY2NTAwMDAwMDAwFQIAERgS...",
"status": "delivered",
"timestamp": "2024-01-20T10:31:00Z"
}
}Conversation Events
conversation.created
Triggered when a new conversation starts.
{
"event": "conversation.created",
"timestamp": "2024-01-20T10:30:00Z",
"data": {
"conversation_id": 123,
"contact_id": 456,
"phone_number": "96650000000",
"created_at": "2024-01-20T10:30:00Z"
}
}conversation.updated
Triggered when conversation details are updated.
{
"event": "conversation.updated",
"timestamp": "2024-01-20T10:35:00Z",
"data": {
"conversation_id": 123,
"status": "active",
"updated_at": "2024-01-20T10:35:00Z"
}
}Order Events
order.created
Triggered when a new order is created.
{
"event": "order.created",
"timestamp": "2024-01-20T11:00:00Z",
"data": {
"order_id": 789,
"conversation_id": 123,
"status": "pending",
"total": 1250.00,
"currency": "SAR",
"created_at": "2024-01-20T11:00:00Z"
}
}order.status.updated
Triggered when order status changes.
{
"event": "order.status.updated",
"timestamp": "2024-01-20T11:30:00Z",
"data": {
"order_id": 789,
"old_status": "pending",
"new_status": "accepted",
"updated_at": "2024-01-20T11:30:00Z"
}
}Webhook Security
Signature Verification
All webhook requests include a signature header for verification:
| Parameter | Type | Required | Description |
|---|---|---|---|
X-Awal-Webhook-Signature | string | Yes | HMAC SHA256 signature of the request body |
X-Awal-Webhook-Timestamp | integer | Yes | Unix timestamp of the request |
Verification Process
// Example: Node.js
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, timestamp, secret) {
// Check timestamp (prevent replay attacks)
const currentTime = Math.floor(Date.now() / 1000);
if (Math.abs(currentTime - timestamp) > 300) { // 5 minutes
return false;
}
// Generate expected signature
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Compare signatures
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}Important
- Always verify the signature before processing webhook events
- Check the timestamp to prevent replay attacks
- Use constant-time comparison for signature verification
Webhook Handling Best Practices
Best Practices
- Respond Quickly: Return 200 OK immediately, then process asynchronously
- Idempotency: Handle duplicate events gracefully using event IDs
- Retry Logic: Implement exponential backoff for failed requests
- Logging: Log all webhook events for debugging
- Error Handling: Return appropriate HTTP status codes
Example Handler
// Example: Express.js webhook handler
app.post('/webhooks/awalchat', async (req, res) => {
try {
// Verify signature
const signature = req.headers['x-awal-webhook-signature'];
const timestamp = req.headers['x-awal-webhook-timestamp'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
timestamp,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Return 200 immediately
res.status(200).json({ received: true });
// Process event asynchronously
processWebhookEvent(req.body);
} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
async function processWebhookEvent(event) {
switch (event.event) {
case 'message.received':
await handleNewMessage(event.data);
break;
case 'message.status.updated':
await handleMessageStatus(event.data);
break;
case 'order.created':
await handleNewOrder(event.data);
break;
// ... handle other events
}
}Event Types Reference
| Parameter | Type | Required | Description |
|---|---|---|---|
message.received | string | No | New message received |
message.status.updated | string | No | Message status changed (sent/delivered/read) |
conversation.created | string | No | New conversation started |
conversation.updated | string | No | Conversation details updated |
order.created | string | No | New order created |
order.status.updated | string | No | Order status changed |
contact.created | string | No | New contact created |
contact.updated | string | No | Contact information updated |
Testing Webhooks
Using ngrok (Local Development)
# Install ngrok
npm install -g ngrok
# Start your local server
node server.js
# In another terminal, expose it
ngrok http 3000
# Use the ngrok URL as your webhook URL
# Example: https://abc123.ngrok.io/webhooks/awalchatWebhook Testing Tool
You can test webhooks using our webhook testing endpoint:
{{base_url}}/webhooks/testSend a test webhook event to your configured endpoint.
Error Handling
Retry Policy
If your webhook endpoint returns an error (4xx or 5xx), we'll retry with exponential backoff:
- 1st retry: After 1 minute
- 2nd retry: After 5 minutes
- 3rd retry: After 15 minutes
- 4th retry: After 1 hour
- 5th retry: After 6 hours
After 5 failed attempts, the event will be marked as failed.
HTTP Status Codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Event processed successfully |
| 400 | Bad Request | Invalid event data (won't retry) |
| 401 | Unauthorized | Invalid signature (won't retry) |
| 500 | Server Error | Temporary error (will retry) |
| 503 | Service Unavailable | Temporary unavailability (will retry) |
Related Sections
Technical Support
Need help with webhooks?
- š§ Email: support@awalchat.com
- š¬ Live Chat: Available in the dashboard
- š± WhatsApp: Contact us directly via WhatsApp
- š Examples: Check Code Examples