Skip to main content
Webhooks push events to your endpoint as they occur — faster than polling, and they cost you no API requests.

Events

call.ended and call.transcript_ready are separate because transcription completes after the call does. If you need the transcript, act on call.transcript_ready — acting on call.ended and immediately fetching will often find nothing there yet.

Setting up an endpoint

1

Expose an HTTPS URL

It must accept POST with a JSON body and return a 2xx quickly.
2

Register it

Add the endpoint in the dashboard and subscribe it to the events you want. Subscribe only to what you’ll use.
3

Store the signing secret

You’re given a secret prefixed whsec_. Keep it in your secret manager — you need it to verify deliveries.
4

Verify every delivery

See below. An unverified webhook endpoint accepts anything anyone posts to it.

Payload

data carries the event-specific detail. Treat unknown fields as additive — new ones may appear without notice, so parse defensively rather than rejecting on unexpected keys.

Verifying signatures

Each delivery carries an X-Webhook-Signature header: the HMAC-SHA256 of the exact raw request body, keyed with your endpoint’s signing secret, hex-encoded.
Compute the HMAC over the raw request body, byte for byte. Parsing the JSON and re-serializing it changes whitespace and key order, and the signature will never match. Capture the raw body before your framework parses it.
Always compare in constant time — timingSafeEqual, compare_digest, hash_equals. A plain == leaks the expected signature to a patient attacker.

Building a reliable consumer

Verify, enqueue, return 2xx. Doing real work inline makes deliveries time out.
Key on the event id and ignore ones you’ve already processed. Assume any event can arrive more than once.
Use the created timestamp rather than arrival order. call.transcript_ready may land before you’ve finished processing call.ended.
Return 401 and log it. A public endpoint accepting unsigned events is an open door into your systems.

Testing

During development, point an endpoint at a request-inspection tool or an ngrok tunnel and trigger a real event — place a test call, or create a contact. Confirm you can verify the signature before writing any business logic on top.

Deactivate rather than delete

If a consumer is broken, deactivate the endpoint while you fix it. Deleting and re-creating issues a new signing secret you’d have to redeploy.