Use webhooks to receive events on your server instead of polling the API.
Connect WhatsApp in the dashboard, then register HTTPS endpoints under Settings → Developer → Webhooks (or the API below). Wazapin POSTs signed JSON to your URL when subscribed events occur.
Configure endpoints
| Action | Method and path |
|---|---|
| List webhook settings | GET /v1/settings/developer/webhooks |
| Create endpoint | POST /v1/settings/developer/webhooks/endpoints |
| Update endpoint | PATCH /v1/settings/developer/webhooks/endpoints/{endpointID} |
| Delete endpoint | DELETE /v1/settings/developer/webhooks/endpoints/{endpointID} |
| Rotate signing secret | POST /v1/settings/developer/webhooks/endpoints/{endpointID}/rotate-secret |
| Send test delivery | POST /v1/settings/developer/webhooks/endpoints/{endpointID}/test |
| List deliveries | GET /v1/settings/developer/webhooks/deliveries |
| Retry a delivery | POST /v1/settings/developer/webhooks/deliveries/{messageID}/retry |
OpenAPI: API reference → Webhooks.
Delivery shape (not a single event_type wrapper)
Unlike some BSP docs that wrap every event as { "type": "…", "data": { } }, Wazapin deliveries follow the standard webhook signing model:
| Where | What |
|---|---|
| HTTP headers | Delivery id (svix-id / webhook-id), timestamp, signature — see Webhook signature examples |
| JSON body | Event-specific fields only (flat object) |
The event name (for example message.new) is the subscription / delivery type. It is not repeated as event_type on the body in the general case.
Use the delivery id header for idempotency (same as event_id in other providers). See Message lifecycle and idempotency.
Messaging event types (common)
Subscribe to these in the app when you integrate send/receive:
| Event | Fires when |
|---|---|
message.new |
New message in a conversation (inbound from a contact, or certain outbound echoes). |
message.sent |
Outbound message sent from your workspace. |
message.status_update |
Delivery/read/failed status changed for a sent message. |
conversation.updated |
Conversation metadata changed (assignment, status, preview, etc.). |
contact.updated |
Contact profile linked to conversations updated. |
template.status_update |
WhatsApp template approval status changed. |
Full list with samples: Webhook event catalog. Filter event types per endpoint in webhook settings.
Example body: message.new (inbound text)
{
"message_id": "9f1fd66d-c37a-4b50-a8c2-b4dca523f9c8",
"conversation_id": "0f89b0f9-74b4-44f9-b9b6-48f6d4de57aa",
"contact_id": "c1a2b3c4-d5e6-7890-abcd-ef1234567890",
"channel_id": "wzp_abc123",
"direction": "inbound",
"from_phone": "6281234567890",
"msg_type": "text"
}Example body: message.status_update
{
"message_id": "9f1fd66d-c37a-4b50-a8c2-b4dca523f9c8",
"conversation_id": "0f89b0f9-74b4-44f9-b9b6-48f6d4de57aa",
"status": "delivered",
"organization_id": "org_123"
}More samples: Webhook payload examples.
Verify signatures
Use the endpoint signing secret (whsec_…) and verify headers on the raw body before parsing JSON.
Delivery and retries
- Respond with
2xxquickly; process asynchronously. - Inspect and retry failed deliveries via the deliveries API.
- Deduplicate by delivery id header +
message_idwhere applicable.
Related pages
- Webhook payload examples
- Webhook signature examples
- Message lifecycle and idempotency
- Example: handle webhook events
List webhook endpoints
curl "https://api.wazapin.com/v1/settings/developer/webhooks" \
--request GET \
--header "X-Api-Key: $WAZAPIN_API_KEY"const response = await fetch("https://api.wazapin.com/v1/settings/developer/webhooks", {
method: "GET",
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.get(
"https://api.wazapin.com/v1/settings/developer/webhooks",
headers={
"X-Api-Key": os.environ["WAZAPIN_API_KEY"],
},
timeout=30,
)
print(response.status_code, response.json())Create webhook endpoint
curl "https://api.wazapin.com/v1/settings/developer/webhooks/endpoints" \
--request POST \
--header "X-Api-Key: $WAZAPIN_API_KEY" \
--json '{
"url": "https://your-app.com/webhook",
"events": [
"message.received",
"message.delivered"
]
}'const response = await fetch("https://api.wazapin.com/v1/settings/developer/webhooks/endpoints", {
method: "POST",
body: JSON.stringify({
"url": "https://your-app.com/webhook",
"events": [
"message.received",
"message.delivered"
]
}),
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.post(
"https://api.wazapin.com/v1/settings/developer/webhooks/endpoints",
headers={
"X-Api-Key": os.environ["WAZAPIN_API_KEY"],
"Content-Type": "application/json",
},
json={
"url": "https://your-app.com/webhook",
"events": [
"message.received",
"message.delivered"
]
},
timeout=30,
)
print(response.status_code, response.json())