Webhooks API
Subscribe to org events, verify deliveries, debug failures, rotate
secrets. All routes require Authorization: Bearer <access_token>
with IdentityOrgPermission.WebhooksEdit (write) or .WebhooksView
(read).
For the conceptual model — when to use webhooks, how delivery works, retry semantics — read Webhooks. This page is the route reference.
Subscribe
POST /identity/organizations/:orgSlug/webhooks
Request
{
url: string // must be HTTPS
events: string[] // event names or ['*']
}Response (201)
{
id: string // 'wh_…'
url: string
events: string[]
secret: string // 'whsec_…' — ONLY returned at creation
enabled: boolean
createdAt: string
// Internal counters reset on create:
consecutiveFailures: number // always 0 here
}Store secret immediately. It is shown only this once.
Errors
| HTTP | code | When |
|---|---|---|
| 400 | validation_failed | URL is not HTTPS, events list invalid. |
| 403 | forbidden | Missing org.webhooks.edit. |
| 409 | conflict | Duplicate (url, events) subscription. Update existing instead. |
List
GET /identity/organizations/:orgSlug/webhooks
Requires org.webhooks.view.
{
items: Array<{
id: string
url: string
events: string[]
enabled: boolean
consecutiveFailures: number
lastDeliveredAt?: string
disabledAt?: string // present after auto-disable
createdAt: string
updatedAt: string
}>
total: number
}No secret in any list response.
Get one
GET /identity/organizations/:orgSlug/webhooks/:id
Same shape as a list item.
Update
PATCH /identity/organizations/:orgSlug/webhooks/:id
{
url?: string
events?: string[]
enabled?: boolean // re-enable after auto-disable
}Setting enabled: true after auto-disable also resets
consecutiveFailures to 0.
Delete
DELETE /identity/organizations/:orgSlug/webhooks/:id
Returns 204.
Rotate the secret
POST /identity/organizations/:orgSlug/webhooks/:id/rotate-secret
Response
{ secret: string }The previous secret becomes invalid immediately. For zero-dropped deliveries:
- Generate the new secret (this endpoint).
- Update your verifier to accept either old or new.
- After a transition window (1–2 minutes), drop the old secret.
@synqid/js’s verifyWebhookSignature accepts a [old, new] array.
Test delivery
POST /identity/organizations/:orgSlug/webhooks/:id/test
Fires a synthetic webhook.test event to the URL.
Response (200)
{
delivery: {
id: string // delivery id
event: 'webhook.test'
url: string
status: 'pending' | 'succeeded' | 'failed_status' | 'failed_timeout' | 'failed_network'
responseCode?: number
responseBodyExcerpt?: string
attemptCount: number
queuedAt: string
deliveredAt?: string
}
}The response captures the first attempt; retries on failure happen in the background.
Delivery logs
GET /identity/organizations/:orgSlug/webhooks/:id/deliveries
Query params:
| Param | Type | Default |
|---|---|---|
status | succeeded | failed_* | pending | (any) |
event | event name | (any) |
since | ISO 8601 | (any) |
until | ISO 8601 | (any) |
limit | 1–200 | 50 |
offset | number | 0 |
Response
{
items: Array<{
id: string
event: string
url: string
status: 'succeeded' | 'failed_timeout' | 'failed_status' | 'failed_network' | 'pending'
responseCode?: number
responseBodyExcerpt?: string // first 200 chars of response body
attemptCount: number
queuedAt: string
deliveredAt?: string
nextAttemptAt?: string // when status is 'pending' and queued for retry
}>
total: number
}Replay a delivery
POST /identity/organizations/:orgSlug/webhooks/:id/deliveries/:deliveryId/replay
Re-attempts the original delivery (same payload, fresh Synq-Delivery
id). Useful when your endpoint was down and you want to redeliver
specific events.
Returns a new delivery record.
Delivery headers (reference)
Every POST to your URL includes:
| Header | Value |
|---|---|
Synq-Signature | HMAC-SHA256(rawBody, secret), hex-encoded |
Synq-Event | Event name, e.g. consent.granted |
Synq-Delivery | UUID of this specific delivery |
Synq-Timestamp | Unix seconds, decimal string |
Content-Type | application/json |
User-Agent | Synq-Webhooks/1.x |
Verification code is in Webhooks.
Rate limits
| Endpoint pattern | Limit |
|---|---|
POST /webhooks | 10/min/org |
POST /webhooks/:id/test | 30/min/webhook |
POST /webhooks/:id/rotate-secret | 5/min/webhook |
GET /deliveries | 60/min/webhook |