POST request to your registered endpoint with a JSON payload describing the event. This makes it easy to keep your own database in sync with message delivery state and react to opt-outs immediately.
Supported Events
| Event | Description |
|---|---|
message.delivered | Message was successfully delivered to the recipient |
message.failed | Message delivery failed after all retry attempts |
message.undeliverable | Message could not be delivered (e.g. invalid number, deactivated account) |
message.optout | Recipient replied STOP or clicked an unsubscribe link |
campaign.sent | All messages in a campaign have been dispatched to carriers |
campaign.completed | Campaign delivery is finished — all messages have reached a final status |
Register a Webhook
Via the Dashboard
Enter your endpoint URL
Provide the HTTPS URL of the endpoint on your server that will receive webhook events (e.g.
https://yourapp.com/webhooks/zexa). HTTP endpoints are not accepted.Select events
Choose the specific events you want to subscribe to. You can subscribe to all events or a targeted subset.
Via the API
You can also register webhooks programmatically:Request Parameters
The HTTPS URL of your endpoint that will receive webhook events. Must use HTTPS — plain HTTP is not accepted.
An array of event names to subscribe to. Subscribe to one or more of:
message.delivered, message.failed, message.undeliverable, message.optout, campaign.sent, campaign.completed. Pass ["*"] to subscribe to all events.Response Fields
The unique webhook identifier, prefixed with
wh_ (e.g. wh_ghi789).The registered endpoint URL.
The list of event names this webhook is subscribed to.
ISO 8601 UTC timestamp of when the webhook was registered.
201 Created):
Error Scenarios
| Status | Error | Description |
|---|---|---|
400 | invalid_request | Missing required fields or malformed JSON body |
401 | unauthorized | API key is missing or invalid |
422 | validation_error | url is not a valid HTTPS URL, or events contains an unrecognised event name |
Webhook Payload
When a subscribed event occurs, Zexa sends aPOST request to your endpoint with a JSON body in the following structure:
| Field | Description |
|---|---|
event | The event type that triggered this delivery |
timestamp | ISO 8601 UTC datetime of when the event occurred |
data | Event-specific payload containing resource IDs, status, and timestamps |
Responding to Webhooks
Your endpoint must return a2xx HTTP status code within 10 seconds of receiving the request. If your endpoint does not respond in time, or returns a non-2xx status, Zexa treats the delivery as failed and retries automatically up to 3 times using exponential backoff (approximately 1 minute, 5 minutes, then 30 minutes between attempts).
Verify Webhook Authenticity
Zexa signs every webhook request with an HMAC-SHA256 signature computed from the raw request body and your webhook secret. The signature is included in theX-Zexa-Signature request header. Always verify this signature before processing the payload to ensure the request genuinely originated from Zexa.
You can find your webhook secret in Settings → Webhooks next to the registered endpoint.
