Skip to main content

Booking flow

The API keeps no session between calls. Everything a later call needs travels in the objects you send back, so store them exactly as you received them.

Lifecycle​

StepEndpointRequired?
1POST /v1/searchYes
2POST /v1/transfer/recheckStrongly recommended immediately before every book
3POST /v1/transfer/bookYes
4POST /v1/transfer/booking-detailsAfter booking, and whenever you show the booking
5POST /v1/transfer/cancelWhen the customer cancels

What to carry between calls​

FromFieldSend it toAs
search offerproviderrecheck, book, booking details, cancelprovider_context.provider
search offerrate_keyrecheck, bookprovider_context.rate_key
search offeroffer_tokenrecheckprovider_context.offer_token
recheck responseoffer_tokenbookprovider_context.offer_token (instead of the offer's token)
book responsesupplier_reference (whole object)booking details, cancelsupplier_reference
book responsethe whole response (optional)booking detailsbook_response
cancel responsethe whole responsebooking detailscancel_response
  • offer_token and supplier_reference.booking_token are opaque, encrypted strings. They cannot be read; any change, or a token from another key or environment, is rejected with 422.
  • Store the whole supplier_reference as JSON and send it back unchanged.
  • offer_id identifies an offer within one search response only; it is regenerated on every search.

Recommended booking record on your side:

Your columnValue
internal_referenceyour own reference, sent at book time
providersupplier_reference.provider
supplier_booking_id, supplier_booking_reffrom the book response (show supplier_booking_ref to customers)
supplier_referenceJSON, unchanged
book_response, cancel_responseJSON, unchanged (recommended)
price_total, price_currencytotal_price and currency from the book response

Offer expiry​

Offers are not held. How long an offer stays bookable depends on the provider, and recheck adapts to it:

Provider behaviourValidity in practiceWhat recheck does
Live price check availableOften short: some quotes expire about 20 minutes after the searchLive price or availability check. An expired quote answers available: false.
No price check available24 hours from the searchChecks the offer's age: up to 24 hours it answers available: true with the search price. The provider confirms availability at book time.

For every provider, an offer_token older than 24 hours from the search is refused with 409 offer_expired. A recheck returns a fresh token with the same expiry: it does not extend the offer.

Recommendation: recheck immediately before booking. If the customer's search is older than about 15 minutes, or recheck answers available: false, search again.

Price changes at recheck​

availableprice_changedWhat to do
truefalseBook with the recheck offer_token.
truetrueShow total_price and currency to the customer. Book only after they accept, with the recheck offer_token.
false–Do not book. Search again; error explains why.

A difference of 0.01 or less is not reported as a change. The book response returns the final price in total_price; compare it with the price you showed.

Booking outcome​

statusMeaningNext step
completedThe provider confirmed the booking.Store supplier_reference, then call booking details.
pendingAccepted but not confirmed yet.Poll booking details (for example after 1, 5 and 15 minutes) until booking.status is confirmed or failed.
failedNothing was booked; error explains why.Show an error. You can recheck and try again, or offer another option.
unknownThe provider did not answer in time after receiving the request, so a booking may exist. error.code is book_outcome_unknown; no supplier_reference yet. We reconcile it with the provider.Do not rebook. Re-send the identical request later: see Idempotency & retries.

Round trips​

A point_to_point search with trip_type: round_trip returns offers with a leg field:

legWhat it isHow to book
outboundpickup → drop-off on pickup_date / pickup_timeOne booking
returndrop-off → pickup on return_date / return_timeOne separate booking
round_tripOne package covering both directions, from providers that sell round trips nativelyOne booking for both directions
  • Sell either one outbound and one return offer (they can come from different providers), or one round_trip offer. Do not combine a round_trip offer with leg offers.
  • Each leg is rechecked, booked, shown and cancelled on its own, with its own internal_reference (for example ORDER-10002-OUT and ORDER-10002-RET).
  • There is no atomic round-trip booking. If the outbound books but the return fails, offer another return or cancel the outbound.

The airport equivalent is a search with both arrival_* and departure_* set; the arrival and departure offers are booked separately in the same way.

Minimal integration​

Pseudo-code
offers = POST /v1/search
offer = customer_choice(offers) # keep provider, rate_key, offer_token

rc = POST /v1/transfer/recheck {provider_context: {provider, rate_key, offer_token: offer.offer_token}}
if HTTP 409 or not rc.available: search again
if rc.price_changed: show rc.total_price; stop unless the customer accepts

bk = POST /v1/transfer/book {provider_context: {provider, rate_key, offer_token: rc.offer_token},
travellers, internal_reference, flight_info}
if HTTP 409 duplicate_booking or bk.status == "unknown": re-send the identical request later; stop
if bk.status == "failed": show bk.error.message; stop
store(bk.supplier_reference, bk)

bd = POST /v1/transfer/booking-details {provider_context: {provider}, supplier_reference}
render_voucher(bd.booking_details)