Skip to main content
Webhooks send a workspace’s events to a URL you own. Each event is a signed POST with a JSON body, sent as it happens. A delivery that fails is retried for about two days. Add endpoints under Developers → Webhooks in the sidebar. Only owners and admins see the Developers section. A workspace can have up to 10 endpoints, and each one picks the events it gets. An endpoint sends events only while the teammate who added it is still an owner or admin of the workspace, the same rule as API keys. If they are removed or demoted, the endpoint is switched off and the page says why. An owner or admin who switches it back on becomes the one it sends under.

Events

Phone and browser-voice transcripts are not sent line by line, because a line is still being written while the caller speaks. Read the full transcript from GET /conversations/{id}/messages when conversation.ended arrives. The widget’s opening message, shown before anyone types, is not sent either.

The request

data holds the same objects the API returns: Answer with any 2xx status, quickly. Do slow work after you respond. Redirects are not followed and count as a failure.

Check the signature

Every request is signed per Standard Webhooks, so any of its libraries can check it. The signed content is webhook-id, webhook-timestamp and the raw body, joined with dots, signed with HMAC-SHA256 using your endpoint’s signing secret (whsec_…).
Without a library:
  1. Base64-decode the secret after the whsec_ prefix. That is the HMAC key.
  2. Compute base64(HMAC-SHA256(key, "<webhook-id>.<webhook-timestamp>.<raw body>")).
  3. webhook-signature holds one or more v1,<signature> values separated by spaces. Accept the request if yours matches any of them, compared in constant time.
  4. Reject a webhook-timestamp more than five minutes from your clock, so an old request cannot be replayed.
Verify the raw body exactly as it arrived. Parsing and re-serialising the JSON changes the bytes and the signature will not match.

Retries

A delivery that does not get a 2xx within 10 seconds is retried, up to seven attempts in all: Retries run every 15 minutes, so a retry can arrive up to 15 minutes after its time.
  • webhook-id is the same on every attempt of one delivery. Use it to ignore one you already handled.
  • Events can arrive out of order. Use timestamp, or the objects’ own timestamps, to order them.
  • An endpoint whose deliveries have all failed for three days is switched off, and the page says why. Fix it, then switch it back on. Events from while it was off are not sent. Read them from the API.

Delivery log, test and rotate

Each endpoint on the settings page shows its last 10 deliveries: the event, whether it was Delivered, Retrying or Failed, the HTTP status, the number of attempts and the error. The log keeps 30 days.
  • Send test event sends a signed webhook.test event straight away and tells you how it went. It is sent even when the endpoint is switched off, so you can check a fix first. It is never retried, and a failed test does not count toward the three days. Changing the endpoint’s address restarts that count.
  • Rotate secret gives you a new signing secret. For the next 24 hours every delivery carries two signatures, one per secret, so you can deploy the new secret without failing any events. After that only the new one signs. Rotating again within those 24 hours replaces only the new secret: the one you started with keeps signing until its 24 hours are up.
  • The signing secret is shown once, when you add the endpoint or rotate it. If you lose it, rotate.
  • Switching an endpoint off stops its deliveries. Remove deletes it and its log.