Webhook events
CustomerHero delivers events to your endpoints over signed POSTs. This page lists every event type you can subscribe to. The signature scheme, retry policy, and HTTP headers are documented in the API reference.
Subscribing
Create a subscription under Settings → Webhooks → New subscription. Pick the event types you want, the destination URL, and an HMAC secret (autogenerated by default). You can also subscribe programmatically via the API.
Use * to subscribe to every event the org emits, including future ones. We never remove an event type without a deprecation window — but if you want to opt-in deliberately, list each event you care about.
Event catalog
Conversation
| Event | Description |
|---|---|
| conversation.created | A new conversation started on any channel. |
| conversation.updated | Top-level fields on a conversation changed (subject, customer, etc.). |
| conversation.tagged | A tag was added or removed. |
| conversation.assigned | Assignee changed (user or team). |
| conversation.status_changed | Status moved between open / pending / closed. |
| conversation.closed | Convenience event — fires alongside conversation.status_changed when status becomes closed. |
| conversation.rated | Customer left a CSAT rating. |
| csat.low_score | Convenience event — fires when a CSAT rating is negative. |
Message
| Event | Description |
|---|---|
| message.created | Any new message in any conversation. Use the role-specific events below if you want one or the other. |
| message.created_by_user | Inbound message from the end customer. |
| message.created_by_assistant | Outbound message generated by the AI. |
| message.created_by_agent | Outbound message sent by a human agent. |
Customer
| Event | Description |
|---|---|
| customer.created | A new customer record was created. |
| customer.updated | First-class fields on a customer changed (name, email, phone). |
| customer.property_updated | A custom property on a customer changed. |
| customer.merged | Two customer records were merged. The payload includes both ids. |
Booking
| Event | Description |
|---|---|
| booking.created | An appointment was booked through a chatbot booking flow. |
| booking.cancelled | A previously booked appointment was cancelled. |
Operational
| Event | Description |
|---|---|
| handoff.triggered | The bot handed a conversation to a human (manual takeover, escalation rule, or guardrail). |
| guardrail.tripped | A response was blocked or rewritten by a content/PII guardrail. |
Payload shape
Every event has the same envelope. The data field contains the resource that changed; for *.updated and *.tagged events, a previous field shows the changed fields' prior values.
{
"id": "evt_01h9k4...",
"type": "conversation.assigned",
"apiVersion": "v1",
"createdAt": "2026-05-09T14:22:01.882Z",
"orgId": "org_k7x9...",
"data": {
"conversation": {
"id": "cnv_b3a8...",
"status": "open",
"assignee": {
"id": "usr_5nf2...",
"name": "Carlos Pérez"
},
"customer": {
"id": "cus_q1k0...",
"email": "jane@acme.com"
}
}
},
"previous": {
"assignee": null
}
}Retries & ordering
A delivery is considered successful on any 2xx. Anything else (including 429, 5xx, and network errors) triggers retry with exponential backoff for up to 24 hours. After that the delivery is marked failed and surfaced in Settings → Webhooks → Activity so you can manually replay it.
Events are not guaranteed to arrive in order. Use the createdAt field on the event envelope as the canonical timestamp, and dedupe with the id field (also mirrored in the Idempotency-Key header). The same event id will never refer to a different payload.
Next steps
See HMAC verification snippets in the API reference → Webhooks.