Booking Flow
Booking Flow Overview
Four calls, in order, with a rate key carrying the state between them.
Searching and booking are deliberately separate. A search is cheap and speculative; a booking is expensive and final. What joins them is the rate key — an opaque handle on one exact priced rate, issued by search and spent by booking.
- 1 Search POST
/searchAsk for a hotel, a city or an area. Each rate comes back with a rateKey and a sell price.
- 2 Book POST
/bookingsRedeem one rateKey with guest names and the price you expect to pay.
- 3 Read GET
/bookings/:idStatus, hotel, rooms, guests, the rate sold and the cancellation ladder, any time after booking.
- 4 Cancel POST
/bookings/:id/cancelPreview the fee with a simulation, then cancel for real.
If the guest is choosing a place rather than a hotel, start one step earlier with Destinations — the countries and cities a search can be run in — and search the one they pick.
Rate Keys
A rate key stands for one rate, on one room, at one property, for one set of dates and occupancy, at one price. Everything the booking needs is already inside it — which is why the book request carries guest names and almost nothing else.
- Opaque. Never parse one, never build one, never store a parsed piece of one. The format is not part of the contract.
- Short-lived. Roughly 30 minutes. After that, booking returns
410 rate_key_expiredand you search again. - Single-use. A second booking with the same key is a
410. This is a safety property, not a limitation: it means a replayed request can never create a second reservation. - Not transferable between environments. A sandbox rate key means nothing to a live key.
Prices Along the Way
Search returns price.net (what Gateway Stream pays the supplier) and price.sell (your price, with your markup already applied). The figure you show a
guest and the figure you send as expectedPrice are both sell.
If the live total at booking time is higher than your expectedPrice, the booking is
rejected with 409 price_changed rather than quietly charged. A lower total is booked
without complaint.
Booking Lifecycle
A booking's status moves through a small, fixed set of values:
CONFIRMED— the supplier confirmed it. This is the happy path.ON_REQUEST— the supplier took the request but has not confirmed. Treat it as neither booked nor free.UNKNOWN— the supplier gave no definite answer and the reservation may or may not exist. Returned with202. Reconcile it; never retry it.FAILED— the supplier refused. Nothing was reserved.CANCEL_REQUESTED— a cancel went out and came back ambiguous. Deliberately neither cancelled nor live.CANCELLED— definitely cancelled.
The full enum, including the payment-stage values, is on Objects and enums.
Putting It Together
A reasonable integration looks like this:
- Search when the guest picks dates. Cache nothing: the rates are already near-live.
- Show
price.sell, the board code, whether the rate is refundable and the first cancellation deadline. - Re-search if the guest has been sitting on results for more than about twenty minutes, so you never hand an expired key to a booking.
- Book with a fresh
Idempotency-Keyper attempt, retrying the identical request with the identical key if the network drops. - Store the
bookingId, thecancelPolicyand thehotelConfirmationNumberagainst your own order. - Simulate before cancelling, so the guest sees the fee before they commit to it.