Booking integration (nisebookings)
This project integrates nisebookings, a hosted booking service (appointments, groups,
recurring series, packages, waiting lists, event tickets). It runs at https://app.nisebookings.com and is reached through the account's public key;
there is no login on the customer side.
Two APIs: the public one (no auth, data-key, creates bookings) and the management API
(/api/v1, scoped nk_… key created under Instellingen → API, server-side only) that configures
settings, opening hours, categories, services, staff, schedules and holidays. Ask the human for the
key; never put it in browser code. The same key also works for the hosted MCP server
(https://app.nisebookings.com/api/mcp, .vscode/mcp.json setup: https://guide.nisebookings.com/api/mcp.html).
Rules
- The booking backend owns all logic. Never compute availability, durations, prices, deposits, discounts or capacity in this project — always ask the API.
- Never trust or reuse a price the user typed:
POST /bookingsandPOST /quoterecompute everything server-side, and only their numbers are authoritative. - Send back the exact
startandstaffIda slot search returned. Do not construct timestamps. - All API instants are UTC ISO strings;
from/untilareYYYY-MM-DDdates in the account's time zone. Display times in thetimeZonereturned byGET services. - Handle
409 {"error":"slot_unavailable"}by re-fetching slots and letting the user pick again. Handle422 {"error":"validation","fields":{…}}by showing the field errors. - One checkout = one order = one payment, even for carts, chains, series and compound services.
- The public key is not a secret (it ships in browser code). The management key (
nk_…) and payment keys are: keep them server-side and out of version control.
Two integration paths
Embed (preferred for a normal web app; no build step, no dependencies):
<script src="https://app.nisebookings.com/widget.js" defer></script>
<nise-booking data-key="<account public key>"></nise-booking>
Event tickets: <script src="https://app.nisebookings.com/events.js" defer></script> +
<nise-events data-key="…">. Add data-lang="en" (or "nl") to either element to override the
account's language, which is the default; the widgets ship Dutch and English. Both scripts log nisebookings@<version> on load; ?v=<version> on
the script URL is a supported cache-bust. WordPress: the nisebookings plugin (listed as nise booking), shortcodes [nise_booking] and
[nise_events].
Headless (custom UI): GET /api/public/<key>/services → GET …/slots?service=&from=&days= →
POST …/quote → POST …/bookings. Chain/cart: POST …/slots with items[] and hold[].
Recurring: POST …/recurrence then book every occurrence with the same series key plus a
series: { "<key>": rule } map. Mollie checkout: send gateway: "mollie" + returnUrl (its origin
must be in the account's allowed sites), redirect to payment.checkoutUrl, then poll
GET …/payments/<token> every 2 s until the status is not pending.
Retries: send Idempotency-Key: <uuid> on POST …/bookings and POST …/tickets and resend the same
body with the same key after a timeout or 5xx — you get the original order back, never a second one.
Events in your own backend (booking created/cancelled, payment completed, …): register a webhook with
POST /api/v1/webhooks, verify the Standard Webhooks signature, dedupe on webhook-id
(https://guide.nisebookings.com/10-webhooks.html).
Verify before claiming success
Use a throwaway sandbox account for this, not the real one: POST https://app.nisebookings.com/api/sandbox
(no auth) → {publicKey, apiKey, expiresAt}, valid 24 h, no mail delivered (read it via
GET /api/v1/outbox), fake Mollie checkout. Details: https://guide.nisebookings.com/08-sandbox.html
- Load the catalogue and one slot list in this project's actual runtime.
- Make one real booking end to end (a local/pay-on-site booking works without payment keys).
- Confirm the result in the admin agenda, and cancel the test booking afterwards if it was not wanted.
Reference
- Full API, error codes and recipes: https://guide.nisebookings.com/04-public-api.html and https://guide.nisebookings.com/openapi.yaml.
- Widget attributes, flows, theming and limits: https://guide.nisebookings.com/03-widget-reference.html.
- Fit check (when this service is the wrong choice): https://guide.nisebookings.com/09-when-to-use.html.