---
title: "Create webhook"
method: POST
path: "/v1/webhooks/settings"
tags: ["Webhooks"]
---

# Create webhook

`POST /v1/webhooks/settings`

Create a new webhook configuration. Maximum 50 webhooks per user.

`name`, `url` and `events` are required. `url` must be a valid URL and `events` must contain at least one event. Whitespace is trimmed from `url` before validation.

Webhooks are automatically disabled after 10 consecutive delivery failures.

A restricted (zrk_) API key can only subscribe to events whose resource group
the key holds; an event outside the key's groups is rejected with 403, so a
restricted key can never create a subscription broader than itself.

`disabledResourceGroups` restricts the subscription itself, independently of
which key or session later reads it. Events in a disabled group are dropped
before delivery to this endpoint, on live delivery and on every replay path
(test fire, redelivery, dead-letter requeue), even if they are listed in
`events`. Omit it to receive everything in `events`, which is how existing
subscriptions behave. A restricted key's own disabled groups are always
unioned in.

## Request body

- object
  - `name` string, required — Webhook name (1-50 characters)
  - `url` string, uri, required — Webhook endpoint URL (must be a valid URL, whitespace trimmed)
  - `secret` string — Secret key for HMAC-SHA256 signature verification
  - `events` string[], required — Events to subscribe to (at least one required)
  - `isActive` boolean — Enable or disable webhook delivery. Defaults to `true` when omitted.
  - `customHeaders` object — Custom headers to include in webhook requests
  - `disabledResourceGroups` string[] — Resource groups this subscription does not receive (opt-out denylist). Omit or send an empty array to receive every event in `events`. Listing a group here drops its events before delivery and on every replay path. Set at creation it applies to everything this subscription ever receives; changed later via PUT it applies to events emitted after the change, with a five-minute tail for events already queued (see that operation). When the caller is a restricted (zrk_) key, that key's own disabled groups are unioned into whatever you send here, so a restricted key can never create a subscription wider than itself.

## Response `200`

Webhook created successfully

- object
  - `success` boolean
  - `webhook` Webhook — Individual webhook configuration for receiving real-time notifications
    - `_id` string — Unique webhook identifier
    - `name` string — Webhook name (for identification)
    - `url` string, uri — Webhook endpoint URL
    - `secret` string — Secret key for HMAC-SHA256 signature verification.
    - `events` string[] — Events subscribed to
    - `isActive` boolean — Whether webhook delivery is enabled
    - `lastFiredAt` string, date-time — Timestamp of last successful webhook delivery
    - `failureCount` integer — Consecutive delivery failures (resets on success, webhook disabled at 10)
    - `customHeaders` object — Custom headers included in webhook requests
    - `disabledResourceGroups` string[] — Resource groups this subscription does not receive (opt-out denylist, same vocabulary and same semantics as the field on API keys). Absent or empty means the subscription receives every event listed in `events`, which is how every subscription created before this field existed behaves. An event whose group is listed here is dropped before delivery even when it is still present in `events`, and the same check runs on every replay path (test fire, redelivery, dead-letter requeue). Editing the denylist applies to every event emitted afterwards; events already queued when the edit landed can still be delivered for up to five minutes after they were enqueued.

## Other responses

- `400` — Validation error or maximum webhooks reached
- `401` — Unauthorized
- `403` — The API key is a restricted key (zrk_ prefix) and may not perform this operation. Three cases. (1) The operation's resource group (see the operation's x-resource-group) is disabled on the key: fix it by creating a key with the group enabled in the dashboard API keys tab and revoking the old one. (2) The operation is admin-plane (x-resource-group admin-plane: API keys, invites, connected apps, member identity), which is never grantable to restricted keys; the error reads "Restricted API keys cannot manage API keys, invites, or member identity." and the fix is a full-access key or the dashboard, never a new restricted key. (3) On webhook subscription writes, delivery-log reads and replays, a named event maps to a resource group the key does not hold, so a restricted key can never create or edit a subscription broader than itself (a no-messages key cannot subscribe to, test-fire, redeliver or read logs for message.* events).

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/f81ca70ea6b9/schema)
