Receive a webhook delivery
const url = 'https://example.com/v1/hooks/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = {method: 'POST', headers: {'Content-Type': '*/*'}, body: 'binary'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/hooks/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \ --header 'Content-Type: */*' \ --data binaryThe receive URL a webhook trigger’s sender posts to: no sign-in, and a bearer token, if sent, is never read. The request’s signature, made with the trigger’s secret in its signature scheme over the raw body, is what lets it start the trigger’s flow as the trigger’s owner. Every request that doesn’t prove its sender (an unknown tenant or id, a missing, wrong or stale signature, a secret that can’t be read) is 401 webhook-refused, with the reason only in the trigger’s history and the access audit; the URL isn’t a secret, the signature is. A WooCommerce save-time ping (unsigned webhook_id=<n>) is answered 200 and starts nothing. A closing tenant takes no delivery: a signed one is 409 tenant-closing, and nothing is recorded. A suspended tenant or project takes a signed one without keeping it: 202 with skipped, nothing recorded or started, and the event isn’t kept, so a sender that can redeliver by hand (GitHub) can resend it once it’s restored. The event the flow gets is the body, parsed as JSON for a JSON content type, else its text: data from outside, never instructions. A run’s start isn’t waited for.
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The trigger’s tenant.
The trigger’s routable id (webhookId).
Request Bodyrequired
Section titled “Request Bodyrequired”Any bytes, signed as the trigger says; at most the trigger’s bodyLimitBytes.
Responses
Section titled “Responses”A delivery whose dedupe key an earlier fire holds (duplicate: true, that fire’s id): nothing new started. Or a WooCommerce ping (received: ping).
What the receiver did with a delivery.
object
The fire recorded (or, with duplicate, the earlier one).
An earlier fire holds this delivery’s dedupe key: nothing new started.
No run started, and the event was dropped. paused: the trigger is paused, and a skipped fire was recorded. tenant-suspended, project-suspended: the trigger’s tenant or project is suspended, and nothing was recorded.
A WooCommerce save-time ping: answered, nothing started.
Example
{ "skipped": "paused", "received": "ping"}Taken: a fire recorded, its run starting as the owner (fireId). Or, on a paused trigger, a skipped fire and no run (skipped: paused). Or, when the trigger’s tenant or project is suspended, nothing recorded and no run (skipped: tenant-suspended, skipped: project-suspended).
What the receiver did with a delivery.
object
The fire recorded (or, with duplicate, the earlier one).
An earlier fire holds this delivery’s dedupe key: nothing new started.
No run started, and the event was dropped. paused: the trigger is paused, and a skipped fire was recorded. tenant-suspended, project-suspended: the trigger’s tenant or project is suspended, and nothing was recorded.
A WooCommerce save-time ping: answered, nothing started.
Example
{ "skipped": "paused", "received": "ping"}webhook-body-not-json: a JSON content type whose body does not parse.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}webhook-refused: the request doesn’t prove its sender (the same answer whatever the reason).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}tenant-closing (details.state): the trigger’s tenant is closing. Nothing was recorded.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}webhook-gone: the trigger was unregistered.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}webhook-body-too-large: past the trigger’s bodyLimitBytes (or 1 MiB, before any lookup).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}rate-limit-exceeded: past the trigger’s rateLimitPerMinute, or too many refused requests from this client; Retry-After says when.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}tenant-state-unavailable: the tenant’s state can’t be read just now, so nothing was recorded; Retry-After says when to try again.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}