The pipeline
Discovery vs live pricing
Two tools play here:- Discovery (
find_destination,flight_calendar,find_dates,lowest_fare) is cached. Returns broad, fast, exploratory results. Prices may be 5-30 minutes stale. - Live pricing (
flight_search,hotel_search) hits the upstream provider directly. Returns atrip_item_tokenyou can add to a trip.
offer_token is not bookable on its own, pass it to flight_search (price-check mode) to get a fresh trip_item_token.
Tokens and IDs
Tokens are scoped, an
offer_token from yesterday won’t work today. Always go through the pipeline fresh.
The identity you submitted is echoed back
Every item the API hands you carries the handle you used to create it, so you can reconcile a trip, a checkout, or a finished booking against your own search results without keeping a side map from your ids to ours. The echo is onitems[] of all four item-bearing responses, POST /v1/trip (the create-and-add receipt) as well as GET /v1/trip/{id}, POST /v1/checkout and GET /v1/trip/{id}/ancillaries, and on every entry of bookings[] once the trip is fulfilled. Which fields appear depends on what the item is:
On a hotel item that is the whole identity:
offer_id and hotel_id, nothing more. The htl_ token already names the room and the rate you picked, so those two fields are enough to tie the item back to the rate in your hotel_search results.
offer_token (the search-index document id) and the provider-native rate id are internal, they change independently of anything you did, and matching on them is a bug waiting to happen.
There is no room_id or rate_id on the echo either, and that is on purpose rather than an omission. The values the platform holds for those are supplier-internal tokens that never matched the room and rate ids hotel_search publishes, so echoing them would have correlated nothing while looking as though it did. offer_id is the field that actually round-trips. Match on the fields above and nothing else.
Three caveats when reconciling
A hotel
offer_id stays the token you submitted even if the rate moved. When a provider re-shops the occupancy, the priced rate can differ from the one your token named, while the echo keeps naming what you sent. That is the point: it is a receipt of your request, not a description of the final rate. Read price, price_changed and hotel_terms for what the rate actually became.Flights are de-duplicated by itinerary, not by fare. Adding the same itinerary twice with two different fares leaves one item, and the echo can name the first fare added rather than the second. If you need both fares on one trip, add them as separate itineraries.
Trip vs cart vs quote
- Trip is the canonical user-facing name across SDK / CLI / MCP / API docs. All public examples and tool names use it (
trip,getTrip,trip_id). - Cart is a legacy internal name that surfaces in one place: some server responses still return
cart_id(numeric, the storage primary key) alongsidetrip_id. They identify the same object. Prefertrip_idin your code. - A quote is the price-locked snapshot of a trip at a point in time.
checkout()schedules a quote internally before creating the Stripe session, you don’t manipulate quotes directly.
Multi-domain trips
A single trip can hold flight items AND hotel items. They go through one Stripe checkout. To build a multi-domain trip:Providers
The API aggregates multiple upstream providers behind a unified API. As of this writing:- Flights: TravelFusion (NDC + LCC), Sabre (GDS).
- Hotels: Nuitée (LiteAPI).
provider field is exposed on responses (and accepted as an override on refund/exchange) for cases where you need to target one explicitly.
Hosted checkout
Jinko owns the payment surface. You never touch credit-card data. Flow:checkout()returns acheckout_urlpointing atapp.gojinko.com/checkout?t=<signed token>. Open the string as returned; never assemble one yourself.- Send the user there (open in browser, deep-link from a widget, etc.).
- They pay on Stripe-hosted UI.
- Stripe webhooks finalize the booking, no client confirm step needed.
- Poll
getTripto watch fulfillment status (awaiting_payment → preparing → prepared → processing → confirming, ending at one of six terminal states:completed,partial,failed,cancelled,expired_quote,exchange_partial_failure).fulfillmentis absent until the customer pays. The flight booking guide has the full table.
Async fulfillment
Booking confirmation isn’t always instant, TravelFusion bookings can take up to 72 hours to confirm with the airline. The API handles this with a job queue (River + Postgres). You pollgetTrip to watch state; the user gets confirmation emails directly from Jinko when their booking lands.
For end-to-end mechanics, see the Flight booking guide or the Flight + Hotel guide for a multi-item trip.