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

# Create a webhook

`POST /v1/webhooks`

## Request

- Base URL: `https://api.postzen.dev`
- URL: `https://api.postzen.dev/v1/webhooks`
- Auth: HTTP bearer

Creates an outbound webhook endpoint. A user may have up to 25 endpoints. This endpoint requires a read-write API key.

## Request body

- WebhookCreateRequest
  - `name` string, required
  - `url` string, uri, required: Public HTTPS endpoint URL.
  - `events` WebhookEvent[], required
  - `profileAccess` 'all_profiles' | 'selected_profiles', required: all_profiles receives events for every profile. selected_profiles requires profileIds.
  - `profileIds` string[]: Required for selected_profiles and omitted or empty for all_profiles.
  - `secret` string, nullable: Optional HMAC signing secret. Omit or send null to create an unsigned endpoint.
  - `customHeaders` WebhookCustomHeader[]
    - `name` string, required: HTTP header name. Content-Type, transport headers, and X-PostZen-* names are reserved.
    - `value` string, required: Plaintext header value. PostZen encrypts it at rest and never returns it.
  - `isActive` boolean

## Response `201`

Webhook created.

- WebhookWriteResponse
  - `message` string, required
  - `webhook` Webhook, required
    - `id` string, required
    - `name` string, required
    - `url` string, uri, required
    - `events` WebhookEvent[], required
    - `profileAccess` 'all_profiles' | 'selected_profiles', required
    - `profileIds` string[], required: Selected profile ids. Empty when profileAccess is all_profiles.
    - `hasSigningSecret` boolean, required: Whether PostZen signs deliveries for this endpoint. The secret itself is never returned.
    - `customHeaderNames` string[], required: Configured custom header names. Header values are never returned.
    - `isActive` boolean, required
    - `disabledReason` 'auto_consecutive_failures' | 'user_disabled'
    - `consecutiveFailures` integer, required
    - `lastDeliveredAt` string, date-time
    - `lastFailedAt` string, date-time
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required

## Other responses

- `400`: Invalid request.
- `401`: Missing or invalid API key.
- `403`: The API key does not have sufficient permission or profile access.
- `409`: The endpoint limit has been reached.
- `429`: Rate limit exceeded. Retry after the interval indicated by the `Retry-After` header.
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/postzen/apis/postzen-public-api.md) · [All operations](https://skmtc.dev/postzen/apis/postzen-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/postzen/apis/postzen-public-api/revisions/40863e3710ec?raw)
