Create a webhook
Register a webhook endpoint for the caller's organization. Requires the `manage` capability. When a matching event fires, the gateway sends an HTTP `POST` to `url` whose body is the event envelope — the same JSON shape delivered over the realtime WebSocket. Use `events` to choose the event types to receive (`["*"]` for all) and `sessionId` to scope deliveries to one session (null/omitted = all of the organization's sessions). **Signing.** If you set a `secret`, every `POST` is signed: the gateway sends the lowercase-hex HMAC-SHA512 of the exact raw request body in the `X-Webhook-Hmac` header (with `X-Webhook-Hmac-Algorithm: sha512`). Recompute it on your end with the same secret to confirm the request really came from the gateway. The secret is stored encrypted and is never returned in any response. **Delivery headers.** Every `POST` also carries `X-Webhook-Request-Id` (the event id — use it to drop duplicate redeliveries) and `X-Webhook-Timestamp` (epoch milliseconds). Any `customHeaders` are applied last and can override the defaults. **Retries.** A delivery that returns non-2xx or fails to connect is retried on the `retryPolicy` schedule — by default exponential backoff (2s, 4s, 8s, …) for up to 15 attempts, after which it is given up (dead-lettered). On success returns `201` with the created webhook. Errors: `422 validation_error` if the body is malformed (e.g. `url` missing or not a valid URL); `403 forbidden` if the caller lacks the `manage` capability.
Send Authorization: Bearer <token>. The router accepts two kinds of token and tries each in turn: a frontend-minted login JWT (verified against the frontend JWKS; the person's org + role are read from it), or an api-key for a script/service (carrying a fixed set of gateway permissions). The bearerFormat: JWT label describes the person-login case.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Whether the webhook is enabled. An inactive (false) webhook is kept but receives no deliveries. Defaults to enabled when omitted on create.
Extra HTTP headers attached to every delivery POST. Applied last, so they can override the gateway's default headers. Use for static auth tokens or routing hints the receiver requires.
Event types to deliver to this webhook. Use ["*"] to receive every event type; an explicit list (e.g. ["message.received", "session.connected"]) delivers only those types; an empty list delivers nothing. See the event catalog for the full set of type names.
How failed deliveries (non-2xx response or connection error) are retried. Omit to use the gateway default: exponential backoff with a 2s base delay (2s, 4s, 8s, …) for up to 15 attempts, after which the delivery is given up (dead-lettered).
Plaintext HMAC signing secret. When set, the gateway signs each delivery: it sends the lowercase-hex HMAC-SHA512 of the exact raw request body in the X-Webhook-Hmac header (alongside X-Webhook-Hmac-Algorithm: sha512), so the receiver can recompute it with the same secret and confirm authenticity. Stored encrypted at rest and never returned in any response. On update: send a new value to rotate the secret; omit the field to leave the stored secret unchanged.
Scope this webhook to a single session: only events produced by that session are delivered. Omit or set to null to receive events from all of the caller organization's sessions. Must reference a session owned by the caller's organization.
The HTTPS endpoint that receives the delivery POSTs. Required on create (validated server-side; a missing or malformed value yields a 422 "validation_error"). The gateway POSTs the event envelope (the same JSON shape pushed over the realtime WebSocket) to this URL as the request body.
Response Body
application/json
application/json
curl -X POST "https://example.com/api/v1/webhooks" \ -H "Content-Type: application/json" \ -d '{}'{ "active": true, "createdAt": 1719662400000, "customHeaders": { "X-Tenant": "acme" }, "events": [ "message", "poll.vote" ], "id": "wh_01J9...", "organizationId": "org_01J9ABC...", "retryPolicy": { "attempts": 15, "delaySeconds": 2, "policy": "exponential" }, "sessionId": "01J9ZX8K2QHV0M3T6R7P4N5W8C", "updatedAt": 1719662400000, "url": "https://example.com/webhooks/wa"}{ "error": { "code": "not_found", "details": { "property1": null, "property2": null }, "message": "session not found" }}List webhooks GET
List the webhook endpoints configured for the caller's organization. Requires the `manage` capability. The response is scoped to the caller's organization — webhooks owned by other organizations are never returned, and secrets are never included. This endpoint returns the full set in one page (the response carries an empty `nextCursor`); no pagination parameters are accepted. Errors: `403 forbidden` if the caller lacks the `manage` capability.
Get a webhook GET
Fetch one webhook by `id`. Requires the `manage` capability, and the webhook must belong to the caller's organization. The signing secret is never returned. Errors: `404 not_found` if no webhook with that id is owned by the caller's organization; `403 forbidden` if the caller lacks the `manage` capability.