Booking Flow
Search
Availability and prices for a hotel, a city, a country or an area, in one call, with a bookable rate key on each rate.
POST
/api/v1/search x-api-keyA search names when (check-in plus either nights or checkOut), who (rooms) and where —
and where can be given three different ways. Everything else has a sensible default.
Saying Where to Look
One of these three is required.
propertyIdsstring[] optional- Specific hotels, each a Gateway Stream
propertyId(uuid) as GET /properties returns it. Several hotels in one request are priced together. destinationobject optional- A place:
{ city, country }, or just{ country }for a whole country. Take them from GET /destinations —countrytakes an ISO-2 code or a name. Every hotel there is priced, up to a per-search ceiling (see below). geoobject optional{ lat, lng, radiusKm }— a real distance filter against stored coordinates. It covers hotels Gateway Stream already holds a position for: a hotel nobody has listed or searched yet is not found this way.
Request Body
Required
checkInstring (YYYY-MM-DD) required- First night of the stay.
roomsobject[] required- One entry per room. Each is
{ adults, childAges }—adultsa positive integer,childAgesa list of ages from 0 to 17 (empty for no children). nights | checkOutinteger | string required- How long the stay is. Send
nights(a positive integer) orcheckOut(YYYY-MM-DD); one of the two is required.
Optional
currencystring (ISO 4217) default "USD"- The currency rates should be quoted in.
nationalitystring (ISO 3166-1 alpha-2) optional- The guests’ nationality. Some rates are priced differently by nationality, and some are restricted by it.
languagestring optional- Preferred language for room names, descriptions and remarks.
filtersobject optionalrefundableOnly(boolean),boards(a list of board codes),minStars(number),maxPrice(number). Applied to the results before they are returned.sort"price_asc" | "price_desc" default "price_asc"- Ordering of the rates within the response.
timeoutMsinteger default 2500- How long to wait for the sources, 1–8000 ms. Whatever has answered when it elapses is what comes back.
Examples
Response
searchIdstring optional- Identifies this search. Worth logging next to the rate keys it produced — it is what Gateway Stream traces a pricing question by.
currencystring optional- The currency every price in the response is quoted in.
propertiesobject[] optional- One entry per hotel that returned rates. See Objects for the full shape.
meta.completeboolean optionalfalsewhen a source did not answer withintimeoutMs(or failed), so rates may be missing. It does not say which source, or why.
Reading the Result
Each property carries its rooms, each room its rates, and each rate
the rateKey that books it. The fields that matter most on a rate:
rateKeystring optional- What POST /bookings redeems. Opaque, single-use, good for about 30 minutes.
price.sellnumber optional- Your price for the whole stay, markup already applied. This is the figure to display and the figure to send as
expectedPrice. price.netnumber optional- What Gateway Stream pays for the room. Shown for reconciliation, not for display.
price.bindingboolean optionaltruemeans the price is guaranteed. A binding rate is never marked down below its quoted gross.board"RO" | "BB" | "HB" | "FB" | "AI" optional- Room only, bed & breakfast, half board, full board, all inclusive.
refundableboolean optional- Whether any cancellation window exists at all. The deadlines and amounts are in
cancelPolicy. cancelPolicyobject[] optional- The cancellation ladder: each entry is
{ from, amount, currency }, meaning “from this moment, cancelling costs this much”. An empty list means no penalty was quoted. nightlyobject[] optional- Per-night breakdown,
{ date, amount }. May be empty. taxesAndFeesobject[] optional{ name, amount, included, payAtHotel }. Anything withpayAtHotel: trueis collected by the hotel and is not part ofprice.sell.paymentType"PREPAID" | "PAY_AT_HOTEL" optional- Who collects the room charge.
Status Codes
- 200
- The search ran.
propertiesmay be empty, and a source may have been slow or failed — readmeta.complete. - 400
validation_error - A malformed body: a bad date, no occupancy, neither
nightsnorcheckOut, none ofpropertyIds/destination/geo, apropertyIdsentry that is not a uuid, or adestinationwith neither a city nor a country. - 401
unauthorized - Missing or invalid
x-api-key. - 429
rate_limited - Too many requests. Back off for
details.retryAfterSeconds. - 503
mode_unavailable - This deployment has no configuration for the environment your key points at.
Practical Notes
- Search close to the booking. Rate keys expire in about half an hour. If a
guest lingers, search again rather than risking a
410at the worst moment. - Give slow sources room. The default
timeoutMsof 2500 favours a fast page. For a results page that can fill in progressively, 6000–8000 catches the slower sources that the default misses. - Don't cache rates. They move, and a cached rate key is a key that is already closer to expiry than you think.
- One hotel may appear twice. The same property reached more than one way is
two entries with two
propertyIdvalues. Deduplicate on your side if that matters to your UI. - A request field Gateway Stream does not know is ignored, not rejected. Check spelling against this page: a misspelt optional field does nothing.