Booking Flow Recipes
Practical recipes for common Experiences integrations. Use these alongside Build an Experiences Booking Experience.
Recipe 1: Basic booking flow
When to use: MVPs, internal tools, and B2B platforms where a simple linear checkout is enough.
Flow
Search → Detail → Availability → Booking options → Prebook → Stripe → Book → Poll / webhookStep-by-step
- Search
GET /v3.0/experiences/tours?language=en¤cy=EURStore: tourId
- Availability + booking-options
GET /v3.0/experiences/tours/{id}/availability?language=en
POST /v3.0/experiences/tours/{id}/booking-optionsStore: optionId, dateTime, slot pricing.totals.net, question answers
- Prebook
POST /v3.0/experiences/tours/{id}/prebooksWith usePaymentSdk: true and selection.price.amount = slot total.
Store: prebookId, transactionId, secretKey
-
Confirm Stripe (client) using
secretKey -
Book
POST /v3.0/experiences/bookingsWith payment.method: TRANSACTION_ID.
Expect: often PENDING_CONFIRMATION
- Confirm via
GET /experiences/bookings/{bookingId}or webhooks untilCONFIRMED
Key decisions
usePaymentSdk: trueis the correct default for Stripe- Keep one
language/currencyfor the session - On 2015, refresh booking-options — do not reuse the old total
Pitfalls
- Using the lowest option price instead of the selected slot total
- Calling book before Stripe succeeds
- Showing a voucher on book response before
CONFIRMED
Recipe 2: Consumer checkout with clear confirmation states
When to use: Consumer-facing sites where trust and conversion matter.
Flow
Search → Tour page → Date & participants → Options/slots
→ Questions + contact → Prebook → Stripe → Book
→ “Confirming…” → Confirmed + voucher emailStep-by-step highlights
- Call booking-options as soon as date + participants are valid
- Show slot price prominently; lock it into the summary
- Collect required
bookingQuestionSchemaanswers before prebook - After book, show a dedicated confirming screen (do not imply ticketed yet)
- Transition to success when status is
CONFIRMEDor voucher webhook arrives
Key decisions
- Prefer partner webhooks for confirmation; poll as backup
- Email on
CONFIRMED/ voucher available, not only on book HTTP 200
Pitfalls
- Auto-closing checkout on book 200 while still
PENDING_CONFIRMATION - Losing
bookingIdfrom the book response (needed for poll / support)
Recipe 3: Handling price mismatch (2015)
When to use: Any time prebook returns 2015, or the guest changes selection after seeing a price.
Detection
const res = await prebook(selection);
if (res.error?.code === 2015) {
const refreshed = await bookingOptions({ date, participants });
showPriceRefresh({ previous: selection.price.amount, options: refreshed });
}UX recommendations
- Explain that the price or availability changed
- Show the new slot total clearly
- One CTA: “Continue with new price”
- Secondary: “Pick another time”
What not to do
- Do not silently retry prebook with the old amount
- Do not force a full search restart if only the slot price changed
Recipe 4: Payment handling
When to use: Every Stripe checkout.
Standard flow
- Prebook with
usePaymentSdk: true→transactionId,secretKey stripe.confirmCardPayment(secretKey, …)on the client- Only then
POST /experiences/bookingswith thattransactionId
Retry notes
- Do not call book if Stripe fails
- If book returns 502 after a successful Stripe confirm, show failure / support — do not tell the guest the experience is booked
- Safe to poll GET booking if you are unsure whether book succeeded
Pitfalls
- Booking with a
transactionIdfrom a different prebook - Reusing an expired prebook after the hold window
Recipe 5: Cancel flow
When to use: Manage-booking or support tools.
Flow
Cancel preview → Show refund quote → Cancel → Wait for CANCELLED (poll / webhook)GET /v3.0/experiences/bookings/{bookingId}/cancel-preview
POST /v3.0/experiences/bookings/{bookingId}/cancelKey decisions
- Always preview before cancel in guest UI
CANCELLATION_REQUESTEDmeans the request was accepted; refund may still be pending
Pitfalls
- Treating cancel 200 as “refund already in the bank”
- Skipping preview and surprising guests with fees
Next
Updated about 3 hours ago

