Webhooks API Reference¶
Outbound webhooks let Centrali send signed HTTP POST requests to your systems whenever matching record events occur.
Use this page for endpoint shapes and lifecycle operations. For delivery semantics, verification examples, and migration guidance, see Outbound Webhooks and Outbound Webhook Migration (6.1).
Authentication¶
All webhook-management endpoints require:
Base URL¶
Webhook Subscription Object¶
{
"id": "6d6f4f59-9c85-4c9d-8a3d-4cfd4db2f6be",
"name": "Order Notifications",
"url": "https://your-app.com/webhooks/centrali",
"events": ["record_created", "record_updated"],
"recordSlugs": ["orders"],
"active": true,
"workspaceSlug": "acme",
"secret": "whsec_...",
"previousSecret": null,
"previousSecretValidUntil": null,
"createdAt": "2026-05-14T14:00:00.000Z",
"updatedAt": "2026-05-14T14:00:00.000Z"
}
Notes:
secretis only returned on create and rotate-secret responsespreviousSecretandpreviousSecretValidUntilare server-managed rotation fields
Create a Subscription¶
POST /webhook-subscriptions
Request Body¶
{
"name": "Order Notifications",
"url": "https://your-app.com/webhooks/centrali",
"events": ["record_created", "record_updated"],
"recordSlugs": ["orders"],
"active": true
}
Notes¶
recordSlugsis optional. Omit it to receive matching events across all collections.- Send an
Idempotency-Keyheader for safe retries.
Retry, Predicate, and Version Fields¶
Create and PATCH accept these optional subscription fields:
| Field | Accepted value |
|---|---|
maxAttempts | Integer 1–20 total attempts; default 5 |
backoffStrategy | fixed or exponential; nullable |
backoffBaseMs | Integer 1,000–86,400,000 ms; nullable |
retryWindowMs | Integer 60,000–604,800,000 ms; null disables the window |
payloadPredicate | Non-empty dot-path/operator map; null clears the filter |
payloadVersion | Registered version; currently only 2025-06 |
Set the strategy and base together, or leave both unset. More than 5 attempts requires both. PATCH validates these invariants after merging with the saved subscription. Without a backoff formula, the default delays are 30 seconds, 2 minutes, 10 minutes, and 30 minutes. Fixed backoff uses the base; exponential backoff uses base * 2^(n-1) after failed attempt n.
Predicates support eq, ne, in, nin, gt, gte, lt, lte, and contains, with all clauses AND-ed against the canonical event before version projection. Predicate misses create filtered rows without HTTP attempts. See Payload Filtering for bounds and comparison semantics.
Omitting payloadVersion on create pins the latest registered version. Deliveries snapshot the version for retries and replay, and expose it in Centrali-Payload-Version. The single registered version establishes versioning infrastructure, not proven multi-version compatibility.
List, Get, Update, Delete¶
List Subscriptions¶
GET /webhook-subscriptions
Returns an array of webhook subscription objects.
Get One Subscription¶
GET /webhook-subscriptions/{id}
Returns the webhook subscription object directly.
Update a Subscription¶
PATCH /webhook-subscriptions/{id}
Editable fields:
nameurleventsrecordSlugsactivemaxAttempts,backoffStrategy,backoffBaseMs,retryWindowMspayloadPredicatepayloadVersion
The signing secret is server-managed. Use the rotate-secret endpoint instead of patching secret fields directly.
Delete a Subscription¶
DELETE /webhook-subscriptions/{id}
Returns 204 No Content on success.
Rotate the Signing Secret¶
POST /webhook-subscriptions/{id}/rotate-secret
Rotation behavior in 6.1:
- Returns the new
secretonce - Moves the previous secret into
previousSecret - Sets
previousSecretValidUntilto 24 hours in the future - Causes outbound deliveries during the grace window to include two space-separated signatures
Send a Synthetic Test Delivery¶
POST /webhook-subscriptions/{id}/test
Dispatch a synthetic event through the production delivery path.
Optional Request Body¶
If omitted, event defaults to the first configured event on the subscription.
Response¶
Returns the created delivery row:
{
"id": "d87fd42a-cf29-4950-9cf9-44ff5df785fd",
"webhookSubscriptionId": "6d6f4f59-9c85-4c9d-8a3d-4cfd4db2f6be",
"workspaceSlug": "acme",
"event": "record_updated",
"attemptCount": 1,
"status": "success",
"httpStatus": 200,
"lastAttemptAt": "2026-05-14T14:12:00.000Z",
"nextAttemptAt": null,
"requestPayload": {
"event": "record_updated",
"workspaceSlug": "acme",
"recordId": "test-2f5f6b7c-8d9e-4012-9f88-41c868f95ca8",
"data": {
"source": "smoke-test"
},
"timestamp": "2026-05-14T14:12:00.000Z",
"isTest": true
}
}
The outbound request includes Centrali-Test-Event: true.
Get Endpoint Health¶
GET /webhook-subscriptions/{id}/health
Response¶
{
"successRate1h": 100,
"successRate24h": 99.2,
"totalDeliveries1h": 6,
"totalDeliveries24h": 243,
"lastFailureAt": "2026-05-14T09:48:21.000Z",
"lastFailureError": "Request failed with status code 500"
}
This is a customer-facing health summary. It does not expose the raw in-process circuit-breaker state.
Delivery History¶
List Deliveries for a Subscription¶
GET /webhook-subscriptions/{id}/deliveries
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
limit | number | Rows per page. Default 50. |
offset | number | Offset into the result set. Default 0. |
status | string | success, failed, retrying, or filtered |
since | string | ISO 8601 timestamp; only deliveries created at or after this time |
until | string | ISO 8601 timestamp; only deliveries created at or before this time |
Response Shape¶
{
"data": [
{
"id": "d87fd42a-cf29-4950-9cf9-44ff5df785fd",
"webhookSubscriptionId": "6d6f4f59-9c85-4c9d-8a3d-4cfd4db2f6be",
"workspaceSlug": "acme",
"event": "record_created",
"attemptCount": 2,
"status": "retrying",
"lastError": "Request failed with status code 500",
"httpStatus": 500,
"lastAttemptAt": "2026-05-14T14:15:00.000Z",
"nextAttemptAt": "2026-05-14T14:17:00.000Z",
"replayedFrom": null,
"createdAt": "2026-05-14T14:14:30.000Z",
"updatedAt": "2026-05-14T14:15:00.000Z"
}
],
"meta": {
"total": 1,
"limit": 50,
"offset": 0
}
}
List rows omit requestPayload and responseBody.
Get a Single Delivery¶
GET /webhook-subscriptions/{id}/deliveries/{deliveryId}
Returns the full delivery record, including requestPayload and responseBody.
Workspace-wide Delivery Helpers¶
GET /webhook-subscriptions/deliveries/recent
GET /webhook-subscriptions/deliveries/failed
Use these endpoints when you need the latest failures or recent activity across every subscription in the workspace.
Replay and Cancel¶
Replay a Delivery¶
POST /webhook-subscriptions/deliveries/{deliveryId}/retry
Returns:
{
"deliveryId": "a0b95d75-67c4-45b7-b3f5-9c3caee5217d",
"replayedFrom": "d87fd42a-cf29-4950-9cf9-44ff5df785fd",
"status": "retrying"
}
Replay creates a new delivery row and re-dispatches the original stored payload.
Cancel a Pending Retry¶
POST /webhook-subscriptions/deliveries/{deliveryId}/cancel
Returns:
{
"deliveryId": "d87fd42a-cf29-4950-9cf9-44ff5df785fd",
"status": "failed",
"lastError": "Cancelled by user"
}
Signing Model¶
6.1 outbound deliveries use:
webhook-idwebhook-timestampwebhook-signature
The signed input is ${webhook-id}.${webhook-timestamp}.${raw-body}. During the 24 hour rotation window, webhook-signature may contain multiple space-separated v1,<base64> values.
For worked verification examples in Node, Python, and Go, see Outbound Webhooks and Outbound Webhook Migration (6.1).