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 / webhook

Step-by-step

  1. Search
GET /v3.0/experiences/tours?language=en&currency=EUR

Store: tourId

  1. Availability + booking-options
GET /v3.0/experiences/tours/{id}/availability?language=en
POST /v3.0/experiences/tours/{id}/booking-options

Store: optionId, dateTime, slot pricing.totals.net, question answers

  1. Prebook
POST /v3.0/experiences/tours/{id}/prebooks

With usePaymentSdk: true and selection.price.amount = slot total.
Store: prebookId, transactionId, secretKey

  1. Confirm Stripe (client) using secretKey

  2. Book

POST /v3.0/experiences/bookings

With payment.method: TRANSACTION_ID.
Expect: often PENDING_CONFIRMATION

  1. Confirm via GET /experiences/bookings/{bookingId} or webhooks until CONFIRMED

Key decisions

  • usePaymentSdk: true is the correct default for Stripe
  • Keep one language / currency for 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 email

Step-by-step highlights

  1. Call booking-options as soon as date + participants are valid
  2. Show slot price prominently; lock it into the summary
  3. Collect required bookingQuestionSchema answers before prebook
  4. After book, show a dedicated confirming screen (do not imply ticketed yet)
  5. Transition to success when status is CONFIRMED or 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 bookingId from 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

  1. Prebook with usePaymentSdk: true → transactionId, secretKey
  2. stripe.confirmCardPayment(secretKey, …) on the client
  3. Only then POST /experiences/bookings with that transactionId

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 transactionId from 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}/cancel

Key decisions

  • Always preview before cancel in guest UI
  • CANCELLATION_REQUESTED means 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



Did this page help you?