Skip to main content

Receive Messages (Webhooks)

Configure webhooks to receive incoming WhatsApp messages and status updates from customers. Exotel delivers message events to your server in real-time.

Webhook Configuration​

Configure your webhook URL in the Exotel Dashboard under WhatsApp > Settings > Webhooks, or via API:

PUT /v2/accounts/<account_sid>/whatsapp/webhook

Request Body​

{
"whatsapp": {
"webhook": {
"incoming_message_url": "https://your-server.com/webhook/whatsapp/incoming",
"status_callback_url": "https://your-server.com/webhook/whatsapp/status",
"verify_token": "your_verification_token"
}
}
}
ParameterTypeRequiredDescription
incoming_message_urlStringYesURL to receive incoming messages
status_callback_urlStringNoURL to receive delivery/read receipts
verify_tokenStringNoToken for webhook verification handshake

Incoming Message Webhook Payload​

When a customer sends a WhatsApp message, Exotel POST's the following to your incoming_message_url:

Text Message​

{
"event": "incoming_message",
"timestamp": "2024-06-15T10:30:00.000Z",
"account_sid": "your_account_sid",
"message": {
"id": "msg_in_001",
"from": "+919876543210",
"to": "your_waba_number",
"timestamp": "2024-06-15T10:30:00.000Z",
"type": "text",
"text": {
"body": "Hello, I need help with my order"
}
},
"contact": {
"wa_id": "919876543210",
"profile": {
"name": "John Doe"
}
}
}

Image Message​

{
"event": "incoming_message",
"message": {
"id": "msg_in_002",
"from": "+919876543210",
"type": "image",
"image": {
"id": "media_abc123",
"mime_type": "image/jpeg",
"sha256": "abc123...",
"caption": "Screenshot of the issue"
}
}
}

Location Message​

{
"event": "incoming_message",
"message": {
"id": "msg_in_003",
"from": "+919876543210",
"type": "location",
"location": {
"latitude": 12.9716,
"longitude": 77.5946,
"name": "Bangalore Office",
"address": "123 MG Road, Bangalore"
}
}
}

Button Reply​

{
"event": "incoming_message",
"message": {
"id": "msg_in_004",
"from": "+919876543210",
"type": "button",
"button": {
"text": "Yes, I confirm",
"payload": "confirm_order_12345"
},
"context": {
"from": "your_waba_number",
"id": "original_msg_id"
}
}
}

Status Callback Webhook​

Delivery and read status updates are sent to your status_callback_url:

{
"event": "message_status",
"timestamp": "2024-06-15T10:30:05.000Z",
"message": {
"id": "msg_out_001",
"status": "delivered",
"recipient": "+919876543210",
"timestamp": "2024-06-15T10:30:05.000Z"
}
}

Status Values​

StatusDescription
sentMessage sent to WhatsApp servers
deliveredMessage delivered to recipient's device
readRecipient has read the message
failedMessage delivery failed

Error Status​

{
"event": "message_status",
"message": {
"id": "msg_out_002",
"status": "failed",
"recipient": "+919876543210",
"errors": [{
"code": 131026,
"title": "Message failed to send because more than 24 hours have passed since the customer last replied"
}]
}
}

Supported Message Types​

TypeDescription
textPlain text messages
imageImage with optional caption
videoVideo with optional caption
audioAudio messages
documentDocument files (PDF, DOC, etc.)
locationLocation coordinates
contactsContact cards
stickerSticker messages
buttonButton reply from interactive messages
list_replyList selection from interactive messages
orderOrder details from catalog messages

Webhook Response​

Your server must return HTTP 200 within 5 seconds to acknowledge receipt. If Exotel doesn't receive a 200 response, it will retry:

RetryDelay
1st30 seconds
2nd2 minutes
3rd10 minutes
4th1 hour

After 4 failed retries, the webhook is marked as failing and alerts are sent.

Security​

Verify incoming webhooks using the signature header:

X-Exotel-Signature: sha256=<hmac_signature>
import hmac
import hashlib

def verify_webhook(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)