---
title: "Register a webhook endpoint"
method: POST
path: "/webhook-endpoints"
tags: ["Webhooks"]
---

# Register a webhook endpoint

`POST /webhook-endpoints`

## Request

- Base URL: `https://developers.ozav.io/v2`
- URL: `https://developers.ozav.io/v2/webhook-endpoints`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Registers an HTTPS endpoint to receive signed event notifications for the
subscribed `enabled_events`. The signing `secret` (`ozav_whsec_`) is
returned exactly once, in this response - store it securely; it is used to
verify delivery signatures and cannot be retrieved again.

The hostname is checked at registration. A host that does not resolve is
refused with `422 WEBHOOK_URL_HOST_NOT_FOUND`, because a typo there fails
silently forever: deliveries never reach anything and the only trace is a
null `response_status` in `GET /webhook-endpoints/{id}/deliveries`. Only a
non-existent hostname is refused - an endpoint behind a firewall, not yet
deployed, or slow to answer registers normally.

## Request body

- WebhookEndpointCreateRequest
  - `url` string, uri, required: HTTPS URL that will receive signed POST deliveries.
  - `enabled_events` WebhookEventType[], required: Event types to deliver to this endpoint.
  - `description` string: Optional human-readable label for the endpoint.

## Response `201`

Endpoint registered; the signing secret is in `secret` (shown once).

- WebhookEndpointWithSecret: Webhook endpoint configuration. Secrets, secret hashes, Vault refs, and internal ids are never returned.
  - `id` string, required: Opaque webhook endpoint identifier, prefixed `ozav_wh_`.
  - `object` 'webhook_endpoint', required: Resource type discriminator; always the literal `webhook_endpoint`.
  - `url` string, uri, required: The HTTPS URL that receives the deliveries. Verify the signature on every request to it (see the Webhooks section); an unverified receiver accepts forged events.
  - `enabled_events` WebhookEventType[], required: The event types this endpoint is subscribed to. An event whose type is not listed here is never delivered to this endpoint, and no record of a skipped delivery is created.
  - `status` 'active' | 'disabled', required: `active` - deliveries are attempted. `disabled` - nothing is delivered and nothing is queued for later; events that occur while disabled are not replayed on re-enable. OZAV does not disable an endpoint on its own. A URL that has failed every delivery for weeks still reads `active`, so `status` alone is not a health signal - read `health`.
  - `description` string, nullable: Free-form label you set. Never used for routing or delivery.
  - `health` object: Read-only delivery health. `last_success_at: null` on an endpoint that has existed for a while means it has never delivered, which is the failure that otherwise stays invisible for weeks. Absent when the aggregate could not be read; its absence never fails the request. `last_error` separates the two opposite causes, because the fix differs: an `HTTP 401` means your server answered and refused (a signature problem), while a transport error such as `dns error: ...` means nothing answered at all (hostname, TLS, firewall) and no signature change will help.
    - `last_success_at` string, date-time, nullable: When a delivery to this endpoint last got a 2xx. `null` means never.
    - `last_failure_at` string, date-time, nullable: When a delivery to this endpoint last failed (non-2xx or transport error). `null` means no failure has been recorded.
    - `last_error` string, nullable: The most recent failure, verbatim - either the HTTP status your server returned or the transport-level error. `null` when nothing has failed.
  - `created_at` string, date-time, required: When the endpoint was registered (RFC 3339, UTC).
  - `updated_at` string, date-time, required: When the endpoint was last modified (RFC 3339, UTC).
  - `secret` string: Signing secret (`ozav_whsec_...`); returned only on creation and rotation.

## Other responses

- `400`: The request is invalid.
- `401`: Missing or invalid API key.

---

[API](https://skmtc.dev/ozav/apis/ozav-api.md) - [All operations](https://skmtc.dev/ozav/apis/ozav-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ozav/apis/ozav-api/revisions/4133dc2109d7?raw)
