Skip to main content

How it works

A webhook is an HTTPS URL registered for your organization. Session events go as a POST to every webhook subscribed to them, so you can react without polling. Each webhook has a url, a list of enabled_events, and a signing secret returned once at creation.

Events

  • "*" subscribes to the session.status_updated firehose.
  • List the types programmatically with List event types.

Delivery payload

All event types share this shape:
Delivery payload
created_at is when the status changed (UTC, RFC 3339, milliseconds). status is any session state. previous_status is null when unknown.

Verify a delivery

Always verify before trusting a delivery. The SDK helper checks the signature, rejects deliveries older than 5 minutes (tune with tolerance_s / toleranceS), and parses the event. On failure it raises WebhookVerificationError. Respond with 400.
Verify the raw bytes: check the body exactly as received (for example await request.body() in FastAPI, express.raw() in Express). Parsing and re-serializing the JSON changes the bytes and breaks the signature. Without an SDK: compute HMAC-SHA256(secret, "{timestamp}." + raw_body), hex-encode it, prefix sha256=, compare it to X-H-Webhook-Signature in constant time, and reject timestamps more than a few minutes old.

Delivery semantics

Deliveries are at-least-once, with a 10-second timeout per attempt. An unreachable endpoint or a non-2xx response is retried with increasing backoff, up to 8 attempts over about 24 hours, then the event is dropped. Each subscribed type is delivered separately: with both session.status_updated and session.failed, a failure sends two deliveries. So:
  • Deduplicate on X-H-Webhook-Delivery, stable across retries. Each event type gets its own event id.
  • Ignore arrival order. A retried old event can land after a newer one. Trust status, previous_status, and created_at.
  • Return 2xx fast, and do slow work after responding.
  • Treat it as a trigger. Fetch the authoritative state with Get session status.
Retrieve reports each webhook’s latest delivery (last_delivery_status, last_delivery_error, last_delivery_at, last_success_at, consecutive_failures), so you can check its health without reading receiver logs.

Test an endpoint

Ping sends a signed ping event through the real delivery path and returns your endpoint’s response synchronously. Use it to check the URL, signature verification, and connectivity.

Rotate the secret

Rotate returns a new secret, and deliveries are signed with it from then on. Pass both secrets to the verify helper until deliveries verify against the new one.

Constraints

  • Target URLs must be https:// and resolve to a public address. A HEAD request checks reachability when you register or change the URL. Deliveries to private or internal hosts fail and count as failed attempts.
  • The number of webhooks per organization is capped.
  • A disabled webhook stays registered but receives nothing.
  • After 50 consecutive failed attempts, a webhook is disabled. Fix the receiver, then re-enable it with Update ({"disabled": false}).