Webhooks push a signed JSON event to your endpoint the moment a ticket changes, so your app can react — create a task, sync status, notify a channel — without polling. Owners add endpoints under Settings → Integrations → Webhooks.
Add an endpoint
- As the account owner, open Settings from the gear icon, then go to Settings → Integrations → Webhooks.
- In Endpoint URL, enter your receiver’s HTTPS URL (for example
https://app.example.com/es-webhook). It must be publicly reachable — private or internal addresses are rejected. - Under Events, tick the events you want. Leaving every box unchecked subscribes the endpoint to all events.
- Click Add endpoint. A signing secret appears once in a highlighted box: Copy this signing secret now — it won’t be shown again. Copy it into your receiver’s config — you need it to verify signatures.
- The endpoint now shows an active chip. You can add up to five endpoints per workspace.
The events
ticket.created— a new ticket was opened (from any source: API, portal, email, widget, or public form).ticket.agent_replied— an agent sent a reply to the customer.ticket.customer_replied— the customer added a message.ticket.status_changed— the ticket moved betweenopenandclosed.ticket.assigned— the ticket was assigned or reassigned to an agent.
The delivery format
Each delivery is an HTTP POST with a JSON body and these headers:
X-ES-Event— the event name.X-ES-Delivery— a stable delivery id, unchanged across retries; use it to deduplicate.X-ES-Workspace— your workspace slug.X-ES-Signature— the HMAC signature to verify (see Verify webhook signatures).User-Agent: EssentialSupport-Webhook/1.0.
The body carries identifiers and state — not message bodies. Fetch the full detail with the read-back API. The deliveryId equals the X-ES-Delivery header.
{
"event": "ticket.agent_replied",
"deliveryId": "66b3a1f0c1d2e3f4a5b6c7d8",
"occurredAt": "2026-08-09T15:20:00.000Z",
"workspace": "acme",
"ticket": {
"id": "66b2f0a1c3d4e5f6a7b8c9d0",
"ref": "A7K2M9Q",
"number": 1042,
"subject": "Invoice charged twice",
"status": "open",
"priority": "high",
"source": "api",
"customer": { "email": "dana@customer.com", "externalId": "u_9", "name": "Dana Lee" }
},
"message": { "id": "66b2f5c2…", "kind": "agent_reply", "createdAt": "2026-08-09T15:20:00.000Z" }
}
A message block appears on the reply events. A changes block appears on ticket.status_changed and ticket.assigned — for example "changes": { "status": { "from": "open", "to": "closed" } }.
Responding to a delivery
Return any 2xx quickly (within about 10 seconds) and process the event asynchronously. Anything else — or a slow response — counts as a failure, and Essential Support retries automatically. Because retries can repeat a delivery, dedupe on X-ES-Delivery. See See webhook deliveries and retry failures.
Test the wiring
On the endpoint row, click Send test to POST a signed sample ticket.created event and see the live status code your endpoint returned. To rehearse the full flow without touching live data, use the Sandbox first.