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

# Webhooks

> The planned Opencals webhook event catalog for booking automations — and how to keep a headless booking site in sync today with polling and revalidation.

<Warning>
  **Webhooks are not yet available.** This page documents the planned design so you can prepare your integration architecture. Event names and payload shapes may change before release. Until webhooks ship, use the [polling and revalidation patterns](#keeping-data-fresh-today) below — they cover the same use cases reliably.
</Warning>

Webhooks will let Opencals notify your application the moment something happens in your store — a booking is created, an order is paid, a customer cancels — so you can drive automations without polling.

## Planned events

The first release focuses on the six events that power the most common merchant automations:

| Event                     | Fires when                       | What merchants automate with it           |
| ------------------------- | -------------------------------- | ----------------------------------------- |
| `appointment.created`     | A new booking is made            | CRM sync, welcome and confirmation flows  |
| `order.paid`              | Payment is captured for an order | Fulfillment, accounting entries           |
| `appointment.canceled`    | A booking is canceled            | Waitlist backfill, freeing resources      |
| `appointment.rescheduled` | A booking is moved to a new slot | Calendar updates, staff notifications     |
| `appointment.completed`   | A booking's end time passes      | Review requests, follow-up sequences      |
| `order.refunded`          | A refund is issued on an order   | Accounting corrections, inventory release |

## How delivery will work

A webhook is an HTTP `POST` from Opencals to an endpoint you host. Each delivery:

* is sent as JSON to the URL you register,
* identifies its event type so one endpoint can handle many events,
* is **signed**, so you can verify the request really came from Opencals,
* expects a `2xx` response. Non-2xx responses are treated as failures and retried with backoff, so make your handler idempotent — the same event may be delivered more than once.

Respond quickly (acknowledge first, process asynchronously) to avoid timeouts on slow handlers.

### Verifying signatures

Deliveries will follow the standard HMAC pattern: a signature header computed over the **raw request body** with your endpoint's secret. The verification you'd write today won't change:

```ts theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyWebhookSignature(
  rawBody: string,
  signatureHeader: string,
  secret: string,
): boolean {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader);
  return a.length === b.length && timingSafeEqual(a, b);
}
```

<Note>
  Verify against the raw, unparsed request body — re-serialized JSON can reorder keys and break the comparison. In Next.js route handlers, use `await request.text()` before parsing.
</Note>

## Keeping data fresh today

Until webhooks ship, two patterns keep an integration accurate:

* **Poll customer-scoped endpoints on your own schedule.** `GET /storefront/appointments` and `GET /storefront/orders` return current state, so a periodic sync job covers CRM, accounting, and follow-up automations. Respect the [rate limits](/docs/quickstart#rate-limits) — a sync every few minutes is well within them.
* **Time-based revalidation for catalog data.** Products, staff, and locations change rarely — Next.js ISR (`revalidate`) or a short CDN cache of a few minutes is usually enough for a headless booking site.
* **Always fetch availability live.** Time slots change with every booking, so call the availability endpoints at request time rather than caching them. The booking flow is also self-correcting: `POST /storefront/cart/checkout/start` re-validates every cart item and reports invalid ones before any payment is taken.

## Related

* [Build a booking page](/docs/guides/build-a-booking-page) — where cached catalog data and live availability fit in the flow.
* [API reference](/docs/api-reference/introduction) — every endpoint the planned events map to.
