Webhooks
هذا المحتوى غير متوفر بلغتك بعد.
Webhooks can be managed in the dashboard under Settings → Webhooks, or through the API when you want them created as part of provisioning a customer.
For what the events contain, see Event reference. For handling them, see Receive messages.
GET /v1/webhooks/events
Section titled “GET /v1/webhooks/events”The catalogue of subscribable events.
Scope: account:read
Read this rather than hard-coding a list, which goes stale the next time an event is added.
{ "data": [ { "value": "message.delivered", "group": "messages", "label": "Message delivered", "description": "WhatsApp confirmed the message reached the recipient's device.", "label_key": "webhooks.events.messageDelivered.label", "description_key": "webhooks.events.messageDelivered.description" } ], "has_more": false}The *_key fields are i18n keys used by our own dashboard. Ignore them and use
label and description.
POST /v1/webhooks
Section titled “POST /v1/webhooks”Scope: webhooks:write · Accepts Idempotency-Key
{ "name": "Order updates", "url": "https://api.example.com/hooks/kmessage", "events": ["message.delivered", "message.read", "message.failed"], "headers": { "X-Internal-Auth": "..." }}| Field | Notes |
|---|---|
name | Required. For your own records. |
url | Required. Public http or https. Private and internal addresses are refused. |
events | Required, at least one. Unknown names are rejected. |
headers | Optional extra headers sent with every delivery. |
secret | Optional. One is generated if you do not supply it. |
is_active | Defaults to true. |
{ "id": "2b3c4d5e-...", "name": "Order updates", "url": "https://api.example.com/hooks/kmessage", "events": ["message.delivered", "message.read", "message.failed"], "is_active": true, "secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0", "created_at": "2026-08-20T10:00:00Z"}The secret appears only here. It is what your endpoint uses to verify that a delivery came from us, and returning it on every read would put it in every log and cache that ever touched the endpoint. Store it now. See Verify webhook signatures.
An unknown event name is refused rather than ignored, because a webhook that looks correctly configured and never fires is indistinguishable from a broken delivery pipeline.
PUT /v1/webhooks/{id}
Section titled “PUT /v1/webhooks/{id}”Scope: webhooks:write
Partial: fields you omit are unchanged. Sending secret rotates it.
events cannot be set to an empty array. Set is_active to false to stop
deliveries; an endpoint subscribed to nothing is one that exists, looks
configured, and can never fire.
POST /v1/webhooks/{id}/test
Section titled “POST /v1/webhooks/{id}/test”Sends a sample test event and reports what your endpoint said.
Scope: webhooks:write
{ "delivered": false, "status_code": 500, "duration_ms": 84, "delivery_id": "8f3a1c2d-...", "response_body": "Internal Server Error", "error": "webhook returned non-2xx status: Internal Server Error"}The HTTP status is 200 even when your endpoint fails. The request to us
succeeded; it was your server that answered 500, and conflating the two would
lose the one fact you need.
Test deliveries appear in the history below, like any other.
GET /v1/webhooks/{id}/deliveries
Section titled “GET /v1/webhooks/{id}/deliveries”Recent attempts, newest first.
Scope: webhooks:read
| Query | Notes |
|---|---|
event | Restrict to one event type |
limit | 1 to 200, default 50 |
{ "data": [ { "id": "1a2b3c4d-...", "delivery_id": "8f3a1c2d-...", "event": "message.delivered", "attempt": 2, "status_code": 200, "success": true, "duration_ms": 112, "request_body": "{\"event\":\"message.delivered\",...}", "response_body": "ok", "created_at": "2026-08-20T09:15:04Z" } ], "has_more": false}Every attempt is recorded, including retries, with the exact payload we sent and what your server replied. History is kept for 7 days.
This is the first place to look when something did not arrive. All attempts for
one event share a delivery_id, so a retry can be told apart from a genuinely
duplicate event. A status_code of 0 means the request never completed:
DNS failure, timeout, or a refused connection.
GET /v1/webhooks · DELETE /v1/webhooks/{id}
Section titled “GET /v1/webhooks · DELETE /v1/webhooks/{id}”List and delete. Delete returns 204.