# API & webhooks

The [**API**](/360/api) page (admin) is where you wire 42min into your own systems.
Today that means **webhooks** — signed HTTPS callbacks that fire whenever a booking
changes. A REST API for reading and writing data programmatically is **coming in a future
release**; in the meantime, webhooks cover the "tell me when something happens" case.

<Screenshot
  src="/help/screenshots/team-and-admin/api.png"
  alt="The 42min API page on the 'API keys' tab, showing an 'API methods are coming soon' placeholder with a 'Coming Soon' badge, alongside a 'Webhooks' tab"
  caption="Admin Center → API. The 'API keys' tab is a placeholder for now; the 'Webhooks' tab is the part that works today."
/>

## Webhooks — what they are

A webhook is a URL on *your* server that 42min calls (an HTTPS `POST`) every time one of
these events happens:

- **`booking.created`** — someone booked a meeting.
- **`booking.rescheduled`** — a booking moved to a new time.
- **`booking.canceled`** — a booking was canceled.

Each webhook you add gets its own **signing secret** (a `whsec_…` string) so you can
verify that a request really came from 42min and wasn't forged.

<Screenshot
  src="/help/screenshots/team-and-admin/webhooks.png"
  alt="The Webhooks tab of the 42min API page: an explanation of signed HTTPS callbacks, an 'Add webhook' button, an empty state ('No webhooks yet'), and a 'For developers' section covering signature verification, delivery & retries, and log retention"
  caption="The Webhooks tab. 'Add webhook' registers an endpoint and which events it wants; the 'For developers' notes spell out the signature, retry, and logging behavior."
/>

## How to set one up

1. Open [**Admin Center → API → Webhooks**](/360/api) and click **Add webhook**.
2. Enter your endpoint **URL** (it must be **HTTPS** — plain `http://` and
   private/loopback addresses are rejected) and pick which **events** it should receive.
3. Save. 42min shows the **signing secret** for that webhook — store it somewhere safe;
   you'll need it to verify requests.
4. On your endpoint, verify the signature (see below) and return a **2xx** status
   quickly. Do any slow work asynchronously so the request doesn't time out.
5. Use the **View logs** panel to watch deliveries and inspect failures.

## What each delivery looks like

The request body is a JSON envelope:

```json
{
  "id": "evt_…",
  "event": "booking.created",
  "createdAt": "2026-05-11T14:03:00.000Z",
  "apiVersion": "2026-04-01",
  "data": { /* the booking */ }
}
```

…and these headers come with it:

- `X-42min-Webhook-Signature: t=<timestamp>,v1=<signature>`
- `X-42min-Webhook-Event: booking.created` (etc.)
- `X-42min-Webhook-Id: <delivery id>`
- `X-42min-Webhook-Attempt: <attempt number>`

**Verifying the signature:** take the `t=` timestamp and the **raw request body**,
build the string `"<timestamp>.<raw body>"`, compute `HMAC-SHA256` of it with your
webhook's signing secret, hex-encode the result, and compare it to the `v1=` value. Also
**reject anything where the timestamp is more than ~5 minutes old** — that stops someone
replaying an old, captured request.

## Delivery & retries

- If your endpoint returns a **non-2xx** status (or the request fails outright), 42min
  **retries** — up to 5 times — with growing gaps: **1 minute, 5 minutes, 30 minutes,
  2 hours, then 12 hours**.
- After **20 consecutive failures**, the webhook is **automatically paused** — fix your
  endpoint, then re-enable it on the Webhooks tab.
- Every delivery attempt is kept for **30 days** and then pruned. **View logs** shows the
  **50 most recent** attempts for a webhook, with the status and response.

## When to use it

- Push new bookings into a CRM, a spreadsheet, or Slack.
- Kick off your own onboarding / fulfillment flow when a meeting is booked.
- Keep an internal system in sync when meetings move or get canceled.
- For "I just want reminders/follow-ups to the invitee or host", you usually don't need
  a webhook — use [workflows](/help/workflows/overview) instead. For pushing booking data
  into Pipedrive specifically, see the [Pipedrive integration](/help/integrations/pipedrive),
  which is purpose-built for that.

## Common pitfalls

- **Endpoint isn't HTTPS (or is internal).** 42min only calls public HTTPS URLs —
  `http://`, `localhost`, and private IP ranges are refused when you add the webhook.
- **Not verifying the signature.** An unverified endpoint will accept anything that finds
  the URL — always check `X-42min-Webhook-Signature` against your secret, and reject old
  timestamps.
- **Verifying against a re-parsed body.** Compute the HMAC over the **raw bytes** you
  received, not over `JSON.stringify(parsedBody)` — re-serializing can change whitespace
  or key order and break the comparison.
- **Slow endpoint → retries pile up.** If you don't answer quickly with a 2xx, 42min
  treats it as a failure and retries; do heavy work after you've acknowledged.
- **Webhook went quiet.** It may have hit 20 consecutive failures and auto-paused — check
  **View logs**, fix the endpoint, and re-enable it.
- **Expecting a full REST API.** It isn't here yet — the "API keys" tab is a placeholder.
  For now, webhooks (and the [Pipedrive](/help/integrations/pipedrive) and
  [Calendly import](/help/integrations/calendly-import) integrations) are the
  programmatic surface.
