> ## Documentation Index
> Fetch the complete documentation index at: https://docs.novacal.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Webhook

> Register a Novacal webhook to receive real-time notifications when events are booked, rescheduled, or canceled, with a signing secret to verify deliveries.

## What this endpoint is for

Register a URL that Novacal calls whenever something happens to an event you host or organize. Webhooks let you react to bookings in real time instead of polling the events endpoint.

## Available events

| Event               | Sent when                                   |
| ------------------- | ------------------------------------------- |
| `event.created`     | A new event is booked                       |
| `event.rescheduled` | An existing event moves to a different time |
| `event.canceled`    | An event is canceled                        |

Subscribe to one or more events per webhook. You can register several webhooks pointing at different URLs.

## Delivery format

Novacal sends a `POST` request with a JSON body:

```json theme={null}
{
  "event": "event.created",
  "created_at": "2026-07-14T10:32:11+00:00",
  "data": {
    "id": "9b1f...",
    "event_type_id": 42,
    "start": "2026-07-20T09:00:00.000000Z",
    "end": "2026-07-20T09:30:00.000000Z",
    "status": "scheduled",
    "organizer": {},
    "booker": {},
    "guests": []
  }
}
```

The `data` object is the same event payload returned by the [Get Event](/api-reference/v1/events/find) endpoint.

## Verifying deliveries

Every delivery carries two headers:

| Header                | Description                                                            |
| --------------------- | ---------------------------------------------------------------------- |
| `X-Novacal-Signature` | HMAC SHA-256 of the raw request body, keyed with your webhook `secret` |
| `X-Novacal-Event`     | The event name, for example `event.created`                            |

Recompute the signature over the raw body and compare it before trusting a request:

```javascript theme={null}
import crypto from "crypto";

const expected = crypto
  .createHmac("sha256", process.env.NOVACAL_WEBHOOK_SECRET)
  .update(rawBody)
  .digest("hex");

const valid = crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(request.headers["x-novacal-signature"])
);
```

Always compare the signature against the **raw** request body, before any JSON parsing or re-serialization.

## Retries

Respond with a `2xx` status code to acknowledge a delivery. Novacal retries a failed delivery up to three times with a short backoff, so your endpoint should be idempotent.


## OpenAPI

````yaml POST /v1/webhooks
openapi: 3.1.0
info:
  title: Events API
  description: Public API for managing event types
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.novacal.io
security:
  - bearerAuth: []
paths:
  /v1/webhooks:
    post:
      description: >-
        Registers a webhook. Novacal sends a signed POST request to the given
        URL whenever one of the subscribed events happens on an event you host
        or organize.
      requestBody:
        description: Webhook payload
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewWebhook'
        required: true
      responses:
        '201':
          description: >-
            Webhook created. The response contains the signing secret used to
            verify deliveries.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
components:
  schemas:
    NewWebhook:
      type: object
      required:
        - url
        - events
      properties:
        url:
          description: The HTTPS URL that Novacal sends deliveries to
          type: string
          example: https://example.com/hooks/novacal
        events:
          description: The events to subscribe to. At least one is required.
          type: array
          minItems: 1
          items:
            type: string
            enum:
              - event.created
              - event.rescheduled
              - event.canceled
          example:
            - event.created
            - event.canceled
        is_active:
          description: Whether the webhook starts active. Defaults to `true`.
          type: boolean
          example: true
    WebhookResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          description: Indicates whether the request was successful
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Webhook'
    Webhook:
      type: object
      properties:
        id:
          description: The unique identifier of the webhook
          type: integer
          example: 1
        url:
          description: The URL Novacal sends deliveries to
          type: string
          example: https://example.com/hooks/novacal
        events:
          description: The events this webhook is subscribed to
          type: array
          items:
            type: string
            enum:
              - event.created
              - event.rescheduled
              - event.canceled
          example:
            - event.created
            - event.canceled
        secret:
          description: >-
            The signing secret used to verify deliveries. Compare it against the
            `X-Novacal-Signature` header.
          type: string
          example: novacal_wh_YOUR_SIGNING_SECRET
        is_active:
          description: Whether Novacal is currently sending deliveries to this webhook
          type: boolean
          example: true
        created_at:
          description: The date and time the webhook was created
          type: string
          format: date-time
        updated_at:
          description: The date and time the webhook was last updated
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````