Skip to main content
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.

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.

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 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.

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.

What’s next?