POST request to every subscribed webhook, so you can react to completions and failures without polling.
Manage webhooks with the CRUD API. Each one has a target url, a list of enabled_events, and a signing secret returned once at creation.
Events
All event types share the same payload shape.
"*" subscribes to the session.status_updated firehose. Each type in enabled_events is delivered independently: subscribing to both session.status_updated and session.failed gets you two deliveries when a session fails, one per type. List the available types programmatically with List event types.
Delivery payload
Each delivery is aPOST with a JSON body:
Delivery payload
The event type, e.g.
session.status_updated.Unique id for this event.
When the status change occurred (UTC, RFC 3339, millisecond precision).
Event payload:
session_id, the new status (queued, pending, running, paused, idle, awaiting_tool_results, completed, failed, timed_out, or interrupted), and the previous_status it transitioned from (null when unknown).Verifying deliveries
Every delivery carries these headers:
Always verify before trusting a delivery. The SDKs ship a helper that checks the signature, rejects stale deliveries (older than 5 minutes by default), and parses the event.
HMAC-SHA256(secret, "{timestamp}." + raw_body), hex-encode it, prefix with sha256=, and compare it to X-H-Webhook-Signature using a constant-time comparison. Reject deliveries whose timestamp is more than a few minutes old to guard against replays.
Delivery semantics
Deliveries are at-least-once, with a 10-second timeout per attempt. If your endpoint is unreachable or returns a non-2xx status, delivery is retried with increasing backoff, up to 8 attempts spanning about 24 hours, after which the event is dropped. Because of retries:- Deduplicate. The same event can arrive more than once. The event
idand theX-H-Webhook-Deliveryheader are stable across retries; skip ids you have already processed. - Ignore arrival order. A retried old event can land after a newer one. Trust the event’s own
status,created_at, andprevious_status, not the order of arrival. - Return 2xx quickly. Any other status counts as a failure and schedules a retry. Do slow work after responding.
last_delivery_status, last_delivery_error, last_delivery_at, last_success_at, and consecutive_failures, so you can check whether an endpoint is healthy, and why it was disabled, without digging through receiver logs.
Testing an endpoint
Ping sends a signedping event through the real delivery path and returns your endpoint’s HTTP response synchronously, so you can validate URL, signature verification, and connectivity before relying on the webhook.
Rotating the secret
Rotate replaces the signing secret without a verification gap:- Deploy your receiver passing both the current and a placeholder for the new secret to the verify helper (it accepts a list).
- Call the rotate endpoint and store the new secret; update the receiver’s secret list.
- Once deliveries verify against the new secret, remove the old one.
Constraints
- Target URLs must be
https://and resolve to a public address. Reachability is verified with aHEADrequest when you register or change the URL, and deliveries to private or internal hosts fail (and count as failed attempts). - The signing
secretis returned only by Create and Rotate. - An organization can register up to 10 webhooks.
- A
disabledwebhook stays registered but receives no deliveries. - After 50 consecutive failed delivery attempts, a webhook is automatically disabled. Fix the receiver, then re-enable it with Update (
{"disabled": false}).