nisebookings docs

Sandbox — a throwaway account for testing

One unauthenticated call gives you a complete, bookable business with its own keys. Point the widget, the public API, the management API or the MCP server at it, make real bookings, read the mails that would have been sent, pay with a fake checkout, and throw it away. Nothing leaves the sandbox: no mail is delivered and no money moves.

curl -s -X POST https://app.nisebookings.com/api/sandbox
{
  "tenantId": "6f1c…",
  "name": "Sandbox 3fa2",
  "publicKey": "9c2e41…",
  "apiKey": "nk_…",
  "scopes": ["catalog:read", "catalog:write", "settings:read", "settings:write", "customers:read",
             "customers:write", "bookings:read", "bookings:write", "payments:read", "payments:write"],
  "expiresAt": "2026-10-13T09:12:44.000Z",
  "endpoints": {
    "publicApi": "https://app.nisebookings.com/api/public/9c2e41…",
    "managementApi": "https://app.nisebookings.com/api/v1",
    "mcp": "https://app.nisebookings.com/api/mcp",
    "widget": "https://app.nisebookings.com/widget.js"
  }
}

The apiKey is a normal management-API key with every scope. It is shown once — keep the response. The publicKey is the sandbox account's public key, exactly as on a real account.

What is in it

Business Sandbox <4 hex>, time zone Europe/Amsterdam, EUR, default mail templates, gateways local and mollie both enabled
Staff Anna and Ben, Monday–Saturday 09:00–17:00 (opening hours the same)
Services (category "Demo") Knippen 30 min €25 (Anna and Ben) · Kleuren 90 min €65 with a €20 deposit rule (Anna; whether it applies follows the deposit mode in the settings) · Groepsles group class, 6 seats, 60 min €15 (Ben)
Events one event a week ahead with one ticket type

The data is fictional. Change anything you like through the management API or MCP — it is your account until it expires. There is no admin login for a sandbox: use the API, MCP and the widget.

Limits

Limit Value
Lifetime 24 hours from creation (expiresAt), then the account and everything in it is deleted
Creation rate 5 sandboxes per hour per client address (the rightmost x-forwarded-for hop our edge appends, else x-real-ip) → 429 {"error":{"code":"rate_limited"}} with Retry-After
Capacity a global cap on live sandboxes → 429 {"error":{"code":"capacity"}} with Retry-After
E-mail never delivered; every mail is recorded with status suppressed (see below)
Payments never real; the Mollie gateway goes to a fake checkout page (see below)

Connect

eval "$(curl -s -X POST https://app.nisebookings.com/api/sandbox |
  jq -r '"export PK=\(.publicKey) NISE_API_KEY=\(.apiKey)"')"

Widget — embed it on any page (a sandbox has no allowed-sites list, so every origin works):

<script src="https://app.nisebookings.com/widget.js" defer></script>
<nise-booking data-key="9c2e41…"></nise-booking>

Public API — examples/headless.mjs runs against it unchanged:

KEY=$PK node headless.mjs

Management API — Authorization: Bearer $NISE_API_KEY on /api/v1:

curl -s -H "Authorization: Bearer $NISE_API_KEY" https://app.nisebookings.com/api/v1/me

MCP — connect your coding agent to the hosted MCP server with the same key:

claude mcp add --transport http nise-sandbox https://app.nisebookings.com/api/mcp \
  --header "Authorization: Bearer $NISE_API_KEY"

Verify mails: the outbox

Every mail the sandbox would have sent — confirmations, staff notices, cancellations — is kept with status suppressed. Read them with GET /api/v1/outbox (or the list_outbox MCP tool), newest first:

curl -s -H "Authorization: Bearer $NISE_API_KEY" \
  "https://app.nisebookings.com/api/v1/outbox?to=ada@example.com"
{
  "data": [
    { "id": "…", "status": "suppressed", "toEmail": "ada@example.com", "toName": "Ada Jansen",
      "subject": "Je afspraak is bevestigd", "text": "…", "html": "…",
      "createdAt": "2026-10-12T09:14:02.000Z", "sentAt": null, "lastError": null }
  ],
  "total": 1
}

Filters: status (pending, sending, sent, failed, suppressed), to (exact address, case-insensitive); pagination limit (≤ 100) and offset. Mails are written by the background worker, so a row can appear a minute after the booking that caused it; poll rather than assert once. The endpoint exists on real accounts too (scope settings:read), where it shows what was actually sent.

Fake payments

Book with gateway: "mollie" and a returnUrl exactly as on a real account. The response's payment.checkoutUrl points to a nise test page, https://app.nisebookings.com/sandbox/pay/<token>, instead of Mollie. It shows the amount and description with two buttons:

Both redirect to your returnUrl with ?nb_pay=<token>, so your return page and its GET /api/public/<key>/payments/<token> polling work exactly as in production. Refunds (POST /api/v1/payments/{id}/refund, scope payments:write) succeed locally without contacting Mollie.

Delete it

A sandbox deletes itself after 24 hours. To delete it now, with its own key:

curl -s -X DELETE -H "Authorization: Bearer $NISE_API_KEY" https://app.nisebookings.com/api/v1/sandbox

204 on success; the keys stop working immediately (401). On a real account this endpoint answers 404 — it can never delete a business.