WhatsApp Gateway
API referenceWebhooks

Get a webhook

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.

GET
/api/v1/webhooks/{id}

Authorization

AuthorizationBearer <token>

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

Path Parameters

id*string

The webhook id. Must reference a webhook owned by the caller's organization, otherwise the request fails with a 404 "not_found".

Response Body

application/json

application/json

curl -X GET "https://example.com/api/v1/webhooks/01HHX5WEBHOOK..."
{  "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"  }}

Create a webhook POST

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.

Update a webhook PATCH

Update the webhook identified by `id` — its `url`, `events`, `sessionId` scope, `secret`, `customHeaders`, `retryPolicy`, or `active` flag. Requires the `manage` capability, and the webhook must belong to the caller's organization. **Secret rotation.** Send a new `secret` to rotate it; omit the field to leave the stored secret unchanged. As elsewhere, the secret is never returned. On success returns `200` with the updated webhook. Errors: `404 not_found` if no webhook with that id is owned by the caller's organization; `422 validation_error` if the supplied fields are invalid (e.g. a malformed `url`); `403 forbidden` if the caller lacks the `manage` capability.