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

EventDescription
conversation.createdA new conversation started on any channel.
conversation.updatedTop-level fields on a conversation changed (subject, customer, etc.).
conversation.taggedA tag was added or removed.
conversation.assignedAssignee changed (user or team).
conversation.status_changedStatus moved between open / pending / closed.
conversation.closedConvenience event — fires alongside conversation.status_changed when status becomes closed.
conversation.ratedCustomer left a CSAT rating.
csat.low_scoreConvenience event — fires when a CSAT rating is negative.

Message

EventDescription
message.createdAny new message in any conversation. Use the role-specific events below if you want one or the other.
message.created_by_userInbound message from the end customer.
message.created_by_assistantOutbound message generated by the AI.
message.created_by_agentOutbound message sent by a human agent.

Customer

EventDescription
customer.createdA new customer record was created.
customer.updatedFirst-class fields on a customer changed (name, email, phone).
customer.property_updatedA custom property on a customer changed.
customer.mergedTwo customer records were merged. The payload includes both ids.

Booking

EventDescription
booking.createdAn appointment was booked through a chatbot booking flow.
booking.cancelledA previously booked appointment was cancelled.

Operational

EventDescription
handoff.triggeredThe bot handed a conversation to a human (manual takeover, escalation rule, or guardrail).
guardrail.trippedA 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.