---
title: "Register a webhook endpoint"
method: POST
path: "/api/v1/webhooks"
tags: ["Public API v1"]
---

# Register a webhook endpoint

`POST /api/v1/webhooks`

## Request

- Base URL: `https://api.vieneu.io`
- URL: `https://api.vieneu.io/api/v1/webhooks`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Registers an HTTPS destination that receives an event when an async job reaches a terminal state, so you can stop polling `GET /v1/tts/{jobId}`.

The response contains the signing **secret exactly once** — store it now, it cannot be retrieved again. Use it to verify the `Vieneu-Signature` header on every event (see the Webhooks guide).

The URL must be `https` and must resolve to a public address. Private, loopback, link-local, CGNAT and reserved ranges are refused here **and** again at the moment of each delivery, so a hostname that is re-pointed at an internal address after registration still fails.

## Request body

- CreateWebhookEndpointDto
  - `url` string, required: HTTPS destination. Must resolve to a public address — private, loopback, link-local, CGNAT and reserved ranges are refused, both when you register the endpoint and again on every delivery attempt.
  - `description` string: Your own label. Shown back to you; never sent to the receiver.
  - `events` string[]: Event types to receive. Defaults to all of them.
  - `apiKeyId` string: Restrict this endpoint to jobs submitted with ONE of your API keys. Omit to receive events for every key on the account. Use it to keep a test key's traffic off your production receiver.

## Response `201`

Endpoint registered. `secret` is present only in this response.

- WebhookEndpointCreatedDto
  - `id` string, required
  - `url` string, required
  - `description` string, required
  - `events` string[], required
  - `status` 'ENABLED' | 'DISABLED', required
  - `apiKeyId` string, nullable: Null when the endpoint receives events for every key.
  - `secretPrefix` string, required: First characters of the signing secret, so you can tell two secrets apart. The secret itself is returned ONCE, at creation and rotation.
  - `secretRotatedAt` string, date-time, nullable
  - `lastDeliveryAt` string, date-time, nullable
  - `lastDeadLetterAt` string, date-time, nullable: When an event to this endpoint last gave up permanently.
  - `createdAt` string, date-time, required
  - `secret` string, required: Signing secret. Shown ONCE — store it now, it cannot be retrieved again. Use it to verify the Vieneu-Signature header on every event.

## Other responses

- `400`: Destination is not an https URL, points at a non-public address, or the account already has the maximum number of endpoints.

## Changes

- **2026-09-16** `98838c7c0e72`: 1 info
  - added the optional property `retryAfterSeconds` to the response with the `400` status
- **2026-09-08** `633d63e717b8`: 2 breaking, 5 info
  - the response property `statusCode` became optional for the status `400`
  - response property `message` list-of-types was widened by adding types `array` to media type `application/json` of response `400`
  - added the optional property `code` to the response with the `400` status
  - added the optional property `error` to the response with the `400` status
  - …3 more
- **2026-09-05** `c9d346918371`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/vieneu/apis/vieneu-api/changes/api/v1/webhooks/post.md)

---

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