Webhook subscriptions
A webhook subscription sends one event type to one HTTPS endpoint of yours. What a delivery looks like, how to verify its signature, and how retries work are on the Webhooks page; this page is the management API.
| Operation | Scope |
|---|---|
GET /webhook_subscriptions |
read |
GET /webhook_subscriptions/:id |
read |
POST /webhook_subscriptions |
read_write |
PATCH /webhook_subscriptions/:id |
read_write |
DELETE /webhook_subscriptions/:id |
read_write |
POST /webhook_subscriptions/:id/test |
read_write |
POST /webhook_subscriptions/:id/rotate_secret |
read_write |
GET /webhook_subscriptions/:id/deliveries |
read |
GET /webhook_event_types |
read |
The subscription entity
{
"id": 31,
"event_type": "Vendor Became Compliant",
"endpoint": "https://hooks.example.com/hounddog",
"description": "Compliance sync",
"disabled": false,
"payload_version": 2,
"consecutive_failures": 0,
"failing_since": null,
"last_error": null,
"last_response_at": "2026-10-07T14:03:12Z",
"created_at": "2026-10-07T12:00:00Z",
"updated_at": "2026-10-07T14:03:12Z"
}
payload_version:2for every subscription created through v2 (signed, the v2 payload). Subscriptions created before v2 are1and keep their original unsigned payload, unchanged; they cannot be converted, so create a new subscription to move to version 2.consecutive_failures,failing_since,last_error: the delivery health. A version 2 subscription whose every attempted delivery for 7 days failed is disabled (disabled: true) with aWebhook Disabledevent.- The signing secret is never part of the entity. It is returned once, by the create and by
rotate_secret, in asecretmember.
GET /webhook_subscriptions, GET /webhook_subscriptions/:id
The account's subscriptions in the collection envelope, and one subscription.
POST /webhook_subscriptions
Body: event_type (required, from the catalog), endpoint (required), description, disabled (default false).
- The endpoint must be
https://. Anhttp://endpoint is 422validation_failednamingendpoint. - The endpoint's host is resolved, and the subscription is refused (422 naming
endpoint) when it resolves to a loopback, private, link-local, carrier-grade NAT or cloud-metadata address, in IPv4 or IPv6 (IPv4-mapped forms included). The check runs again before every delivery, and a delivery to such an address is skipped and counts as a failed attempt. Each delivery connects only to the addresses that check approved (the request still names your host, for TLS and the Host header), so a DNS change between the check and the connection cannot redirect it. If the lookup itself fails at delivery time, nothing is sent and the delivery is retried (DNS lookup failedin the delivery log). - An
event_typeoutside the catalog is 422 namingevent_type.
Response 201 with the entity plus the secret, shown this once:
{ "id": 31, "event_type": "Vendor Became Compliant", "...": "...", "secret": "6b1d..." }
Store the secret; you need it to verify signatures.
This response holds a one-time value, so it is never replayed under an Idempotency-Key (Idempotency).
PATCH /webhook_subscriptions/:id
Updates the fields you send (event_type, endpoint, description, disabled). A changed endpoint is checked as on the create; a changed event_type must be in the catalog. Setting disabled: false re-enables an auto-disabled subscription. disabled: null is 422. Response 200.
DELETE /webhook_subscriptions/:id
Deletes the subscription; pending retries stop. Response 204.
POST /webhook_subscriptions/:id/test
Sends a test delivery to the endpoint now and answers 200 with the delivery record (below). A version 2 subscription's test is signed like any other delivery; a version 1 subscription's is the original unsigned envelope. The test's HTTP request waits at most 10 seconds in total (connect, send and response) and then records a timeout; looking up the endpoint's host comes before that and can add a few seconds when its DNS does not answer. Real deliveries wait up to 30 seconds. Limited to 5 calls a minute per subscription and 10 a minute per account across all its subscriptions (429 rate_limited with Retry-After beyond). The delivery's event is Webhook Test Sent, recorded with your key and naming the subscription by id, event type and host.
POST /webhook_subscriptions/:id/rotate_secret
Replaces the signing secret and returns the entity with the new secret, once. Deliveries after the rotation are signed with the new secret and the old one stops verifying, so accept both secrets on your side while you switch. A version 1 subscription has no secret: rotating it is 422 ("create a new subscription to receive signed payload v2 deliveries").
Never replayed under an Idempotency-Key.
GET /webhook_subscriptions/:id/deliveries
The subscription's delivery attempts over the last 30 days, newest first, in the collection envelope:
{ "id": 77120, "event_id": 9120044, "attempt": 1, "response_code": 200, "duration_ms": 184, "error": null, "created_at": "2026-10-07T14:03:12Z" }
error is null on success, else one of: timeout, connection failed, TLS handshake failed, transport error, address refused (the endpoint's host resolved to a private or internal address, or the endpoint is not a valid URL, so no request was made), DNS lookup failed (the endpoint's host could not be resolved at delivery time, so nothing was sent; it is retried), signing failed (the subscription has no signing secret, so nothing was sent; it is retried, counts toward disabling, and is fixed with rotate_secret), signing unavailable (a temporary problem on our side; nothing was sent; it is retried and does not count toward disabling), or HTTP <code> for a non-2xx response (for example HTTP 503). Response bodies are never recorded.
GET /webhook_event_types
The catalog: every event type you can subscribe to, which is every customer-visible type the app records. Staff-only events are not in it and are never delivered. See Events for what the main types mean.
Each entry names the type and the group it is listed under (abbreviated example):
{
"data": [
{ "event_type": "Vendor Became Compliant", "group": "Compliance" },
{ "event_type": "Certificate Submitted", "group": "Certificates" }
],
"total": 2,
"has_more": false,
"next_page": null
}