Skip to content

Make a booking from your server

This is the production checklist once Quickstart works end to end. It assumes you’re calling the API from your own backend with an sk_ key.

Network calls fail. Rules that keep retries safe:

  • POST /v1/holds always needs an Idempotency-Key header. Generate one UUID per booking attempt, not per HTTP request — if a request times out, retry it with the same key. You get the same hold back (200 instead of 201), never a duplicate.
  • POST /v1/holds/{id}/payment-intent also needs an Idempotency-Key header. Same rule as the hold itself: retry with the same key, get the same PaymentIntent back, never a second charge attempt.
  • POST /v1/holds/{id}/confirm is naturally idempotent — confirming an already-confirmed hold returns the same result, not an error.
  • OTP request and OTP verify are naturally safe to retry too. Re-requesting a code just issues a new one; re-verifying the same correct code again returns the same token until it’s consumed.

A signedQuoteToken expires in 15 minutes (expiresAt in the quote response). If your checkout flow can take longer than that — a guest steps away, fills a long form — re-quote right before creating the hold rather than holding onto a stale token.

The same reasons vocabulary appears on GET /v1/availability and on POST /v1/quotes’s 409. Write one reason-to-message mapping and reuse it in both places — see Availability for the full list.

Your sk_ key gets 300 requests/minute (burst 50) by default. A 429 carries Retry-After — read it and back off; don’t hot-loop on a rejected request. See Rate limits.

  1. Confirm every call above works against sk_test_/pk_test_ keys, including the failure paths (bad code, expired quote, unavailable dates) — not just the happy path.
  2. Ask your operator contact for sk_live_/pk_live_ keys.
  3. Swap the key prefix only. Nothing else about the request shape changes.

Card payment is live: POST /v1/holds/{id}/payment-intent creates a Stripe PaymentIntent for a held reservation, sk_-only, with its own Idempotency-Key requirement — same retry rules as the hold itself. Hand the returned clientSecret to Stripe.js in the guest’s browser and confirm the card there. See Holds and confirmation for exactly what confirm checks once payment is part of the flow.

You don’t need to call confirm yourself on the payment path: our Stripe webhook confirms the reservation automatically once the card charge succeeds. Calling confirm before that happens returns 409 payment_required.

Outbound webhooks for booking events (API-014) aren’t live yet — poll GET /v1/bookings/{id} for now, rather than building a webhook receiver against a guess.