Most real journeys involve more than one item. Jinko’s trip is a single booking unit: you can put a flight and a hotel into the same trip, set the travelers once, and check out once. The user pays a single Stripe charge and receives a single confirmation with a single Jinko booking reference covering both bookings.
This guide builds a Paris weekend (a flight from JFK to CDG and a hotel in Paris) end to end with side-by-side examples for SDK, CLI, and MCP.
The one-line version of the flow:
Prerequisites
- A Jinko account and an API key (
jnk_...). Get one.
- For the SDK path: Node.js 20 or later, then
npm install @gojinko/api-client.
- For the CLI path:
npm install -g @gojinko/cli && jinko auth login --key jnk_....
- For the MCP path: any MCP client connected to
https://mcp.builders.gojinko.com/mcp.
1) Discover the flight
Discover flights for the route and dates, then confirm pricing on the candidate the user picks. This is the same first two steps as the Flight booking guide, so we keep it short.
“From JFK, what can I book to Paris (CDG), leaving June 15 and returning June 22?”
The agent calls find_destination to surface candidates. Pick one; it then calls flight_search to confirm the live price and surface fare options. The agent now has a flight trip_item_token ready to drop into a trip.
2) Find the hotel
Search hotels at the destination for the same dates. Hotel rates are already live offers, no separate price-check step is needed.
“And find me a 4-star hotel near the Louvre for the same dates.”
The agent calls hotel_search and shows you matching hotels and rates. Pick one. The agent now has a hotel htl_* offer ID ready for the next step.
3) Build the trip with both items
Now the key step. Add the flight to a new trip and set travelers in the same call. Then add the hotel to the same trip with a second trip(add_item) call. Both items now live on the same trip and will check out together.
The agent calls trip(add_item + upsert_travelers) with the flight token, then a second trip(add_item) with the hotel offer ID and the same trip_id. From the user’s point of view, this is one continuous conversation.Travelers belong to the trip, not to each item. Set them once with upsert_travelers and they apply to every flight and hotel on the trip.
The trip response now contains two items[]: the flight and the hotel. The total price is the sum of both, in the same currency.
4) Checkout
Call checkout once. You get one Stripe checkout_url covering both items.
The agent calls checkout and opens the checkout in a browser window. The Stripe page shows both items, the combined total, and a single payment.
5) User pays
The user opens checkout_url, sees the flight and the hotel side by side with one total, enters payment once, and Stripe holds the authorization.
6) Fulfillment
Stripe webhooks trigger fulfillment for both items. They book in parallel and the trip is completed once both providers confirm.
fulfillment is absent until the customer pays. POST /v1/checkout does not create a fulfillment record. It quotes the cart and hands you a checkout_url. The record appears, at awaiting_payment, when the customer presses Pay. Before then get_trip returns quote but no fulfillment and no bookings.pending is an item-level status and never appears as a trip’s fulfillment.status. fulfilling is a value of the trip’s own top-level status field, not of fulfillment.status, despite what older versions of this page said.
A two-item trip is not atomic
One item can book while the other fails. This page previously promised “a single, atomic outcome: both succeed or neither does”. That was never true, and it is the assumption most likely to break a multi-item integration.When exactly one provider confirms, the trip lands on partial:
- The item that booked stays booked. Jinko does not roll it back.
- You are charged only for the item that booked. The rest of the authorization is released.
bookings[] contains both entries. Read provider_status on each to tell them apart.
- A
booking.partial webhook fires, carrying the per-item outcome and the amount actually captured.
Deciding what to do next is your call: rebook the failed leg, offer the customer the half that landed, or cancel it. Jinko will not choose for you.
7) Watch the booking land
Poll get_trip until fulfillment.status is terminal. The bookings[] array will contain entries for both the flight and the hotel, including any that failed.
Each entry is { item_id, kind, booking_reference, pnr?, provider_status? }. The field is booking_reference, not booking_ref, and kind is "flight" or "hotel", not type. The agent calls get_trip and reports both confirmation references back to the user. Jinko also sends a single confirmation email covering the full trip.
What’s next?