<!-- Markdown copy of https://docs.creatorain.com/guides/webhooks/ -->
# Webhooks

**Not live yet:** Webhooks on v1 are not live yet. This page describes them as designed. Until then, poll the reads.

## Endpoints

-   `POST /v1/webhook_endpoints` with `{url, events}`. The answer carries a `secret` (`whsec_...`), **once**.
-   `GET`, `PATCH`, `DELETE /v1/webhook_endpoints/{id}`.
-   `POST /v1/webhook_endpoints/{id}/rotate_secret`: the old secret stays valid for 24 hours.
-   `POST /v1/webhook_endpoints/{id}/test`: sends one `ping`.
-   `GET /v1/events`: a poll fallback, 30 days back.

The URL must be `https:` on port 443, on a public address. Redirects count as a failure.

## Envelope

```json
{ "id": "evt_...", "type": "visit.booked", "created": 1793000000, "livemode": true, "account_id": "acct_...", "data": { "object": {} } }
```

## Signature

Each delivery carries one header:

```http
CreatoRain-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">
```

Check it with your endpoint secret. Refuse a timestamp more than 300 seconds old. During a secret rotation, two `v1=` values are sent.

## Retries

A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2, 6 and 12 hours, then 24 hours twice: about 72 hours in all. After 3 days of failures the endpoint is disabled, with a `webhook_endpoint.disabled` event and a banner in the app.

Order is not guaranteed. Dedupe on `id`.

## Events

-   **Locations:** `location.created`, `location.paused`, `location.resumed`, `location.terminated`.
-   **Production:** `visit.booked`, `visit.rescheduled`, `visit.cancelled`, `visit.completed`, `visit.no_show`, `video.posted`, `video.billed`, `video.taken_down`, `video.stats_updated`.
-   **Money:** `balance.topped_up`, `balance.top_up_failed`, `balance.low`, `balance.depleted`, `balance.refunded`, `balance.credited`, `balance.disputed`.
-   **Account:** `api_key.created`, `api_key.revoked`, `webhook_endpoint.disabled`.

`visit.booked` is how your system learns a creator is coming, so you can tell the store.
