Skip to content

Webhooks

Download .md

Webhook endpoints: where events are delivered and how they are signed. How-to: Receive webhooks.

Generated from /openapi/v1.json; interactive version: API reference.

methodpathwhat it doessuccess
GET/v1/webhooksList webhook endpoints200
POST/v1/webhooksRegister a webhook endpoint201
GET/v1/webhooks/{id}Retrieve a webhook endpoint200
PATCH/v1/webhooks/{id}Update a webhook endpoint200
DELETE/v1/webhooks/{id}Delete a webhook endpoint204
POST/v1/webhooks/{id}/rotate-secretChange a webhook endpoint’s signing secret200
POST/v1/webhooks/{id}/testSend a test event200
GET/v1/webhooks/{id}/deliveriesList an endpoint’s deliveries200
GET/v1/webhooks/{id}/deliveries/{delivery_id}Retrieve a delivery200

List webhook endpoints.

List the workspace’s webhook endpoints, newest first, in pages (has_more, next_cursor; pass it back as after). secret is never included. Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
limitqueryinteger
1–200
Max endpoints to return (1–200, default 100). Out of range → 400.
afterquerystringThe previous page’s next_cursor.

Answers 200 with WebhookEndpointList. Errors use the error envelope; common codes: webhooks, every request.

Register a webhook endpoint.

Subscribe a public https URL of at most 2,048 characters to a set of workspace event types. The response includes a one-time secret used to verify delivery signatures (Standard Webhooks / svix scheme) — it is never returned again. Deliveries are signed. A delivery is attempted at once; one not answered 2xx within 10 s is retried on the Standard Webhooks schedule (after 5 s, 5 min, 30 min, 2 h, 5 h, 10 h and 10 h: 8 attempts over about 27.6 h), then given up; an endpoint with 20 given-up deliveries in a row is disabled (re-enable with PATCH { enabled: true }). Webhooks can arrive out of order: order by the envelope seq, dedupe by id. A new endpoint receives v2 payloads (the WorkspaceEventV2 schemas) unless api_version is 2026-10-01. Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Request body: CreateWebhookRequest.

Answers 201 with WebhookEndpoint. Errors use the error envelope; common codes: webhooks, every request.

Retrieve a webhook endpoint.

Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.

Answers 200 with WebhookEndpointRead. Errors use the error envelope; common codes: webhooks, every request.

Update a webhook endpoint.

Change the url, event_types, description or api_version, or toggle enabled. Re-enabling clears the failure state. A new api_version applies to deliveries not yet attempted. Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.

Request body: UpdateWebhookRequest.

Answers 200 with WebhookEndpointRead. Errors use the error envelope; common codes: webhooks, every request.

Delete a webhook endpoint.

Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.

Answers 204 with no body. Errors use the error envelope; common codes: webhooks, every request.

Change a webhook endpoint’s signing secret.

Replaces the signing secret and returns the new one once. The old secret stops working at once: every later delivery attempt, retries included, is signed with the new one, so a receiver that still checks the old secret rejects them (and they count as failed deliveries) until it is updated. Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.

Answers 200 with WebhookEndpoint. Errors use the error envelope; common codes: webhooks, every request.

Send a test event.

POSTs one sample webhook.test event to the endpoint, synchronously, signed with its current secret like a real delivery (10 s timeout, no redirects), and returns what the receiver answered. Works on a disabled endpoint too. Nothing is stored: no event in /v1/events, no delivery, no change to the failure count. At most 10 tests per workspace per minute (429 webhook_test_rate_limited). Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.

Answers 200 with WebhookTestResult. Errors use the error envelope; common codes: webhooks, every request.

List an endpoint’s deliveries.

The endpoint’s deliveries of the last 7 days, newest first, in pages (has_more, next_cursor; pass it back as after, with the same status). Each one says whether it succeeded, is retrying or was given up, how often it was tried, and what the receiver answered (response_status, error). The reply body and the request body are on GET /v1/webhooks/{id}/deliveries/{delivery_id}. Nothing is re-sent: replay an event from GET /v1/events?after=<seq - 1> (with &api_version=v2 for the v2 body). Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.
limitqueryinteger
1–100
Max deliveries to return (1–100, default 50). Out of range → 400.
afterquerystringThe previous page’s next_cursor. A cursor of another endpoint or another status → 400 invalid_cursor.
statusquerystring
all, pending, succeeded, failed, exhausted, problems; default all
Only deliveries in this state. problems is failed and exhausted together, without the deliveries dropped because the endpoint was off or the event expired (error.code endpoint_disabled / retention). Anything else → 400.

Answers 200 with WebhookDeliveryList. Errors use the error envelope; common codes: webhooks, every request.

GET /v1/webhooks/{id}/deliveries/{delivery_id}

Section titled “GET /v1/webhooks/{id}/deliveries/{delivery_id}”

Retrieve a delivery.

One delivery, with the exact body that was (or will be) POSTed (payload), the headers of the latest try without the signature, and the first 1,000 characters of the receiver’s reply on a failed try (response_excerpt). An endpoint of another workspace, a delivery of another endpoint, and a missing one are the same 404 not_found. Owners and admins only: a key whose owner has the Agent role in the workspace gets 403 insufficient_role.

Parameters

nameintypedescription
idpathstring, requiredThe endpoint short id (whe-…) or UUID.
delivery_idpathstring (uuid), requiredThe delivery’s id.

Answers 200 with WebhookDeliveryDetail. Errors use the error envelope; common codes: webhooks, every request.

fieldtypedescription
idstring, requiredShort id, e.g. “whe-0000000001”.
objectstring, required
always webhook_endpoint
urlstring (uri), required
event_typesarray of string, requiredSubscribed types, or ["*"] for all.
enabledboolean, required
api_versionstring, required
2026-10-01, v2
The payload version this endpoint receives: v2 (WorkspaceEventV2, the default for a new endpoint) or 2026-10-01 (WorkspaceEvent, the legacy format every endpoint that existed before release v1.84.0.0 keeps). A change applies to deliveries not yet attempted; a delivery in retry keeps the version it was first sent in.
created_atstring (date-time), requiredWhen the endpoint was created (ISO 8601).
updated_atstring (date-time), requiredWhen the endpoint was last changed (ISO 8601).
descriptionstring or null
secretstringSigning secret (“whsec_…”). Returned ONLY by the create response and by POST /v1/webhooks/{id}/rotate-secret — never on reads.

Example: see Receive webhooks.

A webhook endpoint as list, read and update answer it: never with its secret (only create and rotate-secret return that).

fieldtypedescription
idstring, requiredShort id, e.g. “whe-0000000001”.
objectstring, required
always webhook_endpoint
urlstring (uri), required
event_typesarray of string, requiredSubscribed types, or ["*"] for all.
enabledboolean, required
api_versionstring, required
2026-10-01, v2
The payload version this endpoint receives: v2 (WorkspaceEventV2, the default for a new endpoint) or 2026-10-01 (WorkspaceEvent, the legacy format every endpoint that existed before release v1.84.0.0 keeps). A change applies to deliveries not yet attempted; a delivery in retry keeps the version it was first sent in.
created_atstring (date-time), requiredWhen the endpoint was created (ISO 8601).
updated_atstring (date-time), requiredWhen the endpoint was last changed (ISO 8601).
descriptionstring or null

Example: see Receive webhooks.

fieldtypedescription
objectstring, required
always list
dataarray of WebhookEndpointRead, required
has_moreboolean, required
next_cursorstring or null, requiredPass as after for the next page; null on the last.

Example: see Receive webhooks.

fieldtypedescription
urlstring (uri), requiredPublic https endpoint. Rejected (400) if it resolves to a private/loopback/link-local/metadata address.
event_typesarray of string
each conversation.created, turn.completed, confirmation.requested, confirmation.resolved, spend.recorded, run.completed, message.received, message.sent, message.status_updated, campaign.started, campaign.paused, campaign.resumed, campaign.completed, campaign.canceled, campaign.waiting, campaign.window_opened, meta_response.completed, meta_chat.updated, call.ringing, call.answered, call.completed, call.failed, *
Optional; defaults to ["*"] (all events).
descriptionstring
≤ 500 chars
api_versionstring
2026-10-01, v2; default v2
The payload version the endpoint receives: v2 (default) or 2026-10-01 (legacy). See /platform-api/events/#payload-versions.
{
"url": "https://example.com/file",
"event_types": [
"conversation.created"
],
"api_version": "v2"
}
fieldtypedescription
urlstring (uri)
event_typesarray of string
each conversation.created, turn.completed, confirmation.requested, confirmation.resolved, spend.recorded, run.completed, message.received, message.sent, message.status_updated, campaign.started, campaign.paused, campaign.resumed, campaign.completed, campaign.canceled, campaign.waiting, campaign.window_opened, meta_response.completed, meta_chat.updated, call.ringing, call.answered, call.completed, call.failed, *
enabledboolean
descriptionstring
≤ 500 chars
api_versionstring
2026-10-01, v2
Switch the payload version: v2 or 2026-10-01. Left out, the endpoint keeps the one it has. See /platform-api/events/#payload-versions.
{
"event_types": [
"conversation.created"
],
"api_version": "v2"
}
fieldtypedescription
objectstring, required
always webhook_test
okboolean, requiredThe receiver answered 2xx.
statusinteger or null, requiredThe HTTP status, or null with no answer.
status_textstring or null, requiredThe status phrase, e.g. “OK”.
duration_msinteger, required
errorstring or null, required
timeout, connect, redirect
Why no answer came: timeout (none within 10 s), connect, or redirect (redirects are not followed). Null when the receiver answered.
response_excerptstring or null, requiredThe first 1,000 characters of the reply body, when there was one.
{
"object": "webhook_test",
"ok": false,
"status": null,
"status_text": null,
"duration_ms": 1,
"error": "timeout",
"response_excerpt": null
}

One event’s delivery to one endpoint. Deliveries are kept for 7 days. The list leaves out the reply and the body: read one delivery for those.

fieldtypedescription
idstring (uuid), requiredThe delivery’s id.
objectstring, required
always webhook_delivery
endpoint_idstring, requiredThe endpoint’s short id, e.g. “whe-0000000001”.
event_idstring, requiredThe event’s id (evt_…), also sent as the webhook-id header.
event_typestring or null, requiredThe event’s type; null once the event left the 7-day log.
seqinteger, requiredThe event’s position in the workspace’s log. Replay from this event with GET /v1/events?after=<seq - 1>.
statusstring, required
pending, succeeded, failed, exhausted
pending (not tried yet), succeeded (answered 2xx), failed (will be retried at next_attempt_at), exhausted (given up, or dropped: see error.code).
attemptsinteger, requiredTries made so far (at most 8).
next_attempt_atstring (date-time) or null, requiredWhen the next retry is due; set only when status is failed.
response_statusinteger or null, requiredThe HTTP status of the latest try, or null when there was no answer.
errorobject or null, requiredWhy the latest try failed, or why the delivery was dropped; null when it did not.
error.codestring, required
endpoint_disabled, retention, timeout, redirect, connect, http, render
http (answered, not 2xx), timeout (no answer within 10 s), connect (no connection), redirect (redirects are not followed), render (the body could not be built; nothing was sent), endpoint_disabled (dropped: the endpoint was off), retention (dropped: the event expired before it could be delivered).
error.messagestring, requiredThe stored text, e.g. “HTTP 502”.
api_versionstring, required
2026-10-01, v2
The payload version this delivery was sent in (a retry resends it), or, not tried yet, will be sent in.
created_atstring (date-time), required
updated_atstring (date-time), required
last_attempt_atstring (date-time) or null, requiredWhen the latest try was signed (its webhook-timestamp); null before the first.

Example: see Receive webhooks.

One delivery, with the body sent and the receiver’s reply.

fieldtypedescription
idstring (uuid), requiredThe delivery’s id.
objectstring, required
always webhook_delivery
endpoint_idstring, requiredThe endpoint’s short id, e.g. “whe-0000000001”.
event_idstring, requiredThe event’s id (evt_…), also sent as the webhook-id header.
event_typestring or null, requiredThe event’s type; null once the event left the 7-day log.
seqinteger, requiredThe event’s position in the workspace’s log. Replay from this event with GET /v1/events?after=<seq - 1>.
statusstring, required
pending, succeeded, failed, exhausted
pending (not tried yet), succeeded (answered 2xx), failed (will be retried at next_attempt_at), exhausted (given up, or dropped: see error.code).
attemptsinteger, requiredTries made so far (at most 8).
next_attempt_atstring (date-time) or null, requiredWhen the next retry is due; set only when status is failed.
response_statusinteger or null, requiredThe HTTP status of the latest try, or null when there was no answer.
errorobject or null, requiredWhy the latest try failed, or why the delivery was dropped; null when it did not.
error.codestring, required
endpoint_disabled, retention, timeout, redirect, connect, http, render
http (answered, not 2xx), timeout (no answer within 10 s), connect (no connection), redirect (redirects are not followed), render (the body could not be built; nothing was sent), endpoint_disabled (dropped: the endpoint was off), retention (dropped: the event expired before it could be delivered).
error.messagestring, requiredThe stored text, e.g. “HTTP 502”.
api_versionstring, required
2026-10-01, v2
The payload version this delivery was sent in (a retry resends it), or, not tried yet, will be sent in.
created_atstring (date-time), required
updated_atstring (date-time), required
last_attempt_atstring (date-time) or null, requiredWhen the latest try was signed (its webhook-timestamp); null before the first.
response_excerptstring or null, requiredThe first 1,000 characters of the receiver’s reply on a failed try.
payloadmap of string to any or null, requiredThe exact JSON body that was (or will be) POSTed, in api_version’s format. Null once the event left the 7-day log, or when the body could not be built.
headersobject, requiredThe headers of the latest try. webhook-signature is never returned.
headers.webhook-idstring, required
headers.webhook-timestampstring or null, requiredUnix seconds, as Standard Webhooks defines it; null before the first try.

Example: see Receive webhooks.

fieldtypedescription
objectstring, required
always list
dataarray of WebhookDelivery, required
has_moreboolean, required
next_cursorstring or null, requiredPass as after for the next page; null on the last.

Example: see Receive webhooks.