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.
Retry safely
Section titled “Retry safely”Network calls fail. Rules that keep retries safe:
POST /v1/holdsalways needs anIdempotency-Keyheader. 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 (200instead of201), never a duplicate.POST /v1/holds/{id}/payment-intentalso needs anIdempotency-Keyheader. 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}/confirmis 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.
Handle the quote’s 15-minute clock
Section titled “Handle the quote’s 15-minute clock”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.
Handle 409 unavailable the same way twice
Section titled “Handle 409 unavailable the same way twice”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.
Respect rate limits
Section titled “Respect rate limits”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.
Go live
Section titled “Go live”- 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. - Ask your operator contact for
sk_live_/pk_live_keys. - Swap the key prefix only. Nothing else about the request shape changes.
Take payment before you confirm
Section titled “Take payment before you confirm”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.
What’s still coming
Section titled “What’s still coming”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.