Event webhooks
Have IconEngage POST a signed event to your system when a message arrives, a status changes, a template is decided and more; check deliveries, replay them and send test events.
An event webhook sends an HTTPS POST to your system the moment something happens in IconEngage, such as a customer's message or a delivery receipt. Each delivery is signed so you can check it came from IconEngage.
Note: Owners, Admins and Developers can manage event webhooks. Creating one also needs permission to view API keys.
Event webhooks send events out to your system. To have your system start a flow in IconEngage, use Inbound webhooks instead.
Before you start
Every webhook is signed for one of your API keys and only sends what that key is allowed to read. So create an API key first. The key needs, for example, messages.read for message events.
Your endpoint must be a public https:// address.
Create a webhook
- Go to Settings › Event webhooks.
- Click New webhook.
- In Name, enter a name (up to 120 characters).
- In Endpoint URL, enter your
https://address. - In Sign for API key, choose the key the webhook belongs to. You cannot change this later.
- Under Events, tick the events you want (see below).
- Click Create webhook.
- If asked, confirm your identity with your two-factor code or password.
- Copy the secret from Copy your signing secret now and store it safely. You need it to verify signatures.
- Click I have copied it.
Note: The signing secret is shown only once. The list later shows only its last characters (Secret ends …).
If the chosen key cannot read what an event sends, the form says which permission it needs. Choose another key or drop that event.
Events you can subscribe to
Public API events
These have the documented body described below.
| On screen | Event type | Sent when | Key needs |
|---|---|---|---|
| API: message received | message.received | A customer sent a message to one of your WhatsApp numbers. | messages.read |
| API: message status | message.status | A message you sent was sent, delivered, read or failed (with why). | messages.read |
| API: template status | template.status | WhatsApp approved, rejected, paused, disabled, reinstated or flagged a template. | templates.read |
| API: conversation assigned | conversation.assigned | A conversation was assigned: claimed, transferred or routed. | messages.read |
| API: conversation closed | conversation.closed | A team member resolved a conversation. | messages.read |
| API: contact opted out | contact.opted_out | A contact opted out of your messages. | contacts.read |
Automation events
You can also subscribe to the events that start automation flows: Message received, Conversation opened, Tag added, Tag removed, Field changed, Intent detected, Conversation attributed, Order placed, Payment received, Payment failed and Cart abandoned. Their bodies differ from the public API events. Message received here is not the same as API: message received.
What a delivery looks like
Each public API event is a POST with a JSON body:
{
"id": "0b8f6a52-…",
"type": "message.status",
"version": 1,
"occurred_at": "2026-10-11T09:31:12Z",
"data": {
"message": { "id": "6f1c2e8a-…", "wamid": "wamid.HBg…", "type": "template", "template_name": "order_confirmation" },
"status": "delivered",
"timestamp": "2026-10-11T09:31:12Z",
"conversation": { "id": "b0e4…", "contact_id": "2a7d…", "phone_number_id": "1234567890" },
"contact": { "id": "2a7d…", "wa_id": "919876543210", "display_name": "Asha" },
"failure": null
}
}idis the event's id. It is the same on every retry and replay, so use it to ignore events you have already handled.versionis the version ofdata's shape. A change that could break your code would come as a new version.data.testistrueon a test event and absent otherwise.- Events carry ids and states, never secrets or file contents.
Each delivery also carries these headers:
| Header | Contains |
|---|---|
X-IconEngage-Signature | The signature. See Verify webhook signatures. |
X-IconEngage-Event | The event type, the same as type |
X-IconEngage-Event-Id | The event id, the same as id |
Idempotency-Key | The event id again, for frameworks that dedupe on this header |
X-IconEngage-Delivery | The delivery's id, as the delivery log shows it |
X-IconEngage-Attempt | 1 for the first attempt, then counting up |
X-IconEngage-Timestamp | The signing time, for convenience only (it is not signed) |
Responding, retries and ordering
- Answer with any
2xxstatus within 10 seconds to accept a delivery. The response body is ignored. - Any other answer, a timeout or a connection failure is retried with growing gaps (starting at 30 seconds and doubling, at most 6 hours apart), up to 8 attempts. After that the delivery is marked Dead letter and can be replayed.
- Delivery is at least once: you may receive the same event more than once. Dedupe on
id. - Events can arrive out of order. Use
occurred_atto order them.
Tip: Accept the delivery quickly and do slow work afterwards, so you stay inside the 10 seconds.
Manage your webhooks
The Event webhooks list shows each webhook's Name, Sends to, Events, Signed for and Status.
- Turn a webhook on or off with the switch in Status (On / Off).
- Suspended: IconEngage pauses a webhook that keeps failing, and says why (for example "Paused after too many failed deliveries"). Fix the cause, then turn it on again. That resumes sending and resets the failure count.
- Edit changes the name, endpoint and events. Delete stops events at once.
Check deliveries and replay one
- Go to Settings › Event webhooks.
- Open the webhook's actions menu and choose Delivery log.
- Filter by Status if you want: Waiting, Sending, Delivered, Failed or Dead letter.
Each delivery shows every attempt with its time, your system's response code and how long it took. Bodies are never stored, so none are shown.
To try a delivery again:
- Click Replay on the delivery.
- Click Replay to confirm.
The replay is a new attempt of the same delivery, with the same event id. Earlier attempts stay in the log. A delivery that is still waiting or sending cannot be replayed.
Send a test event
Use a test event to check your endpoint and your signature check without waiting for real activity.
- Open the webhook's Delivery log.
- Choose one public API event, or Every API event it lists.
- Click Send test event.
The test is a sample of the event with made-up values and data.test set to true. It reads none of your data. It is signed and logged like a real event and appears in the log with a Test badge. The webhook must be on. Test events exist for the public API events only, not for automation events.
Manage webhooks from the API
A key can also create, change, delete and test its own subscriptions with /webhook-subscriptions. See The IconEngage public API.
Still need help?
Write to us at [email protected] and tell us what you were trying to do. Already a customer? Sign in to IconEngage — the same articles are under Help in the app.