/api/v1/webhooks
Register one, and disclose its signing secret ONCE.
- Scope
webhooks:manage- Rate limit
- 20 requests / min
- Idempotency
Idempotency-Keysupported
Authentication
Send your key as Authorization: Bearer …. It must carry the scope webhooks:manage; a key without it receives 403 forbidden.
Headers
Idempotency-KeystringReplays the first response for a repeated request. Reusing a key with a different body is idempotency_key_reused (409), never a silent replay.
Request body
application/jsonrequiredurlstringrequiredThe https:// endpoint to deliver to. http://, private hosts and IP literals are refused.
eventsstring (enum)[]requiredEvent types to subscribe to. At least one. Duplicates are collapsed, not refused.
productsarray | nullnullableProduct slugs this endpoint should hear about. Omit or send an empty array to hear about every product — the default. Naming products matters when several teams integrate under one organization: without a filter, this endpoint also receives the other lines' events. At most 60, and slugs are not checked against the catalog, so a typo produces a quiet endpoint rather than a failed registration.
descriptionstring | nullnullableYour own label for this endpoint, at most 200 characters after trimming.
Refused parameters13
Sending any of these returns 400 validation_error naming the field. Each entry explains what to do instead.
secret'secret' is not accepted: the signing secret is generated server-side (32 bytes of CSPRNG entropy) and returned exactly once, on this response. A caller-chosen secret would let an endpoint be signed with a low-entropy value, and would travel through request logs and the idempotency record on its way here.
signing_secret'signing_secret' is not accepted: the signing secret is generated server-side and returned exactly once, on this response.
signingSecret'signingSecret' is not accepted: the signing secret is generated server-side and returned exactly once, on this response.
mode'mode' is not accepted: a subscription is always created in the mode of the API key that registered it, and only ever receives that mode's events. Use a live key to register a live endpoint.
livemode'livemode' is not accepted: a subscription is always created in the mode of the API key that registered it.
status'status' is not accepted: a subscription is created active. Its status is set by delivery outcomes (failing) and by DELETE (removed).
enabled'enabled' is not accepted: a subscription is created active. Remove it with DELETE /v1/webhooks/:id.
active'active' is not accepted: a subscription is created active. Remove it with DELETE /v1/webhooks/:id.
id'id' is not accepted: the subscription id is assigned by the platform and returned on this response.
org_id'org_id' is not accepted: a subscription always belongs to the organization the API key belongs to.
api_key_id'api_key_id' is not accepted: the registering key is recorded automatically and is not caller-supplied.
webhook_url'webhook_url' is not the parameter name on this endpoint; send 'url'.
idempotency_key'idempotency_key' is not accepted as a body field: send it as the 'Idempotency-Key' HTTP header.
Response
201application/jsonidstringrequiredurlstringrequiredeventsstring[]requiredThe event types this endpoint is subscribed to.
productsstring[]requiredProduct slugs this endpoint is limited to. EMPTY means every product, which is the default — an endpoint that named no products hears about all of them, exactly as every endpoint did before this filter existed.
modestringrequiredlive or test — the mode of the API key that registered it.
statusstringrequiredactive or failing. disabled never reaches a response.
descriptionstring | nullrequirednullablecreated_atstring | nullrequirednullableupdated_atstring | nullrequirednullablesecrettype not publishedrequiredErrors
The statuses this operation can return, with the error.code values behind each. Every error body is the shared envelope described under Errors in Getting started.
400validation_error401unauthorized403forbidden409idempotency_key_reused429rate_limit_exceeded500internal_error