> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dev.gojinko.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-room hotel booking preview

> Search and check out one hotel offer covering several rooms in the development environment.

<Note>
  This preview uses the development REST API and a separate Builder MCP test instance.
  The existing Unified MCP / ChatGPT app and its widgets keep their current interface.
  Availability in development does not announce a production release. Use the test
  Builder URL supplied for this preview, rather than the production MCP endpoint.
</Note>

## One occupancy requests one room

Each item in `occupancies` requests one room. One item is a single-room search;
two items request two rooms. There is no `room_booking_mode` option.
Existing single-room integrations can keep their request and response handling.

Use `https://api.dev.gojinko.com` with a development API key. On REST, destination
selectors such as `query` are top-level fields. Builder MCP nests them under
`destination`; for example, `destination: { query: "Paris" }`.

```javascript theme={null}
const api = async (path, body) => {
  const response = await fetch(`https://api.dev.gojinko.com/v1/${path}`, {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.JINKO_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  })
  if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`)
  return response.json()
}

const dateInDays = (days) =>
  new Date(Date.now() + days * 86400000).toISOString().slice(0, 10)

const search = await api('hotel_search', {
  query: 'Paris',
  checkin: dateInDays(60),
  checkout: dateInDays(63),
  occupancies: [{ adults: 2 }, { adults: 2 }],
  guest_nationality: 'FR',
  currency: 'EUR',
})
```

## Select an offer for the entire stay

Each hotel has two top-level lists:

* `rooms` contains room metadata, including room names, photos and amenities when available.
* `offers` contains bookable prices and terms. Its `room_rates` identify the included
  room for each requested occupancy through `room_id` and `occupancy_number`.

Every `room_rates[].room_id` references an entry in the same hotel's `rooms`.
An offer with a missing room reference is omitted as a whole. The same room type
can appear twice in `room_rates`, with different occupancy numbers.

The following is an abbreviated example, with illustrative identifiers:

```json theme={null}
{
  "hotel_id": "example-hotel",
  "rooms": [
    { "room_id": "42", "room_name": "Deluxe King", "rates": [] },
    { "room_id": "43", "room_name": "Classic Twin", "rates": [] }
  ],
  "offers": [{
    "offer_id": "htl_example_bundle",
    "total_amount_money": {
      "value": 60000,
      "currency": "EUR",
      "decimal_places": 2,
      "display": "EUR 600.00"
    },
    "room_rates": [
      { "room_id": "42", "occupancy_number": 1, "occupancy": { "adults": 2 } },
      { "room_id": "43", "occupancy_number": 2, "occupancy": { "adults": 2 } }
    ]
  }]
}
```

`total_amount_money` is the price for all included rooms and nights. Add the
offer once. Do not multiply its price by the room count or create a cart item
for each `room_rate`. Room entries carry no allocated customer price.

For single-room searches, deprecated `rooms[].rates[]` remains available alongside
`offers[]`, with the same offer token and customer price. For multiple rooms,
`rooms[].rates` is empty. New integrations should select `hotel.offers[]`.

## Add travelers and get checkout

Choose an offer matching the guest's requirements before continuing:

```javascript theme={null}
const hotel = search.hotels.find((candidate) => candidate.offers?.length)
const offer = hotel?.offers.find((candidate) => candidate.room_rates.length === 2)
if (!offer) throw new Error('No two-room offer returned; adjust the search.')

const trip = await api('trip', {
  add_item: { trip_item_token: offer.offer_id },
  upsert_travelers: {
    travelers: [
      { first_name: 'Avery', last_name: 'Morgan', passenger_type: 'ADULT' },
      { first_name: 'Jordan', last_name: 'Lee', passenger_type: 'ADULT' },
      { first_name: 'Riley', last_name: 'Chen', passenger_type: 'ADULT' },
      { first_name: 'Taylor', last_name: 'Patel', passenger_type: 'ADULT' },
    ],
    contact: { email: 'avery@example.com', phone: '+33612345678' },
  },
})

const checkout = await api('checkout', { trip_id: trip.trip_id })
console.log(checkout.checkout_url)
```

Replace the example identities with the actual travelers. `hotel_room_guests`
can be omitted: adult travelers supply room leads in order, repeating from the
beginning when there are fewer adults than rooms. All rooms can use the same
booking contact. Explicit per-room lead overrides remain available, including
the same lead for multiple rooms.

Open the exact returned `checkout_url`, including its signed `t` token. A trip ID
alone does not authenticate checkout. The checkout page keeps one hotel item,
shows its included rooms, and lets the customer review one total. Checkout can
reprice the stay, so use the current checkout total before payment.

For a flight plus multi-room hotel trip, add the checked flight token to this
same `trip_id` through `trip.add_item`. The cart then has one flight item and one
hotel item covering both rooms. One checkout covers the whole cart. Flights still
require all travelers and their airline-required details.

## Confirmation and cancellation

A mixed flight-and-hotel trip sends a combined confirmation at payment authorization,
then separate flight and hotel confirmations after capture. Shared hotel leads keep
all their room labels. Each room's cancellation terms are shown separately;
one non-refundable room does not mean every room has zero refund.

The booking remains the cancellation unit. This preview does not add partial-room
cancellation or change the `hotel_cancel` request. Retrieve the current booking and
its confirmed terms before cancellation. Explicitly unknown or unparseable confirmed policies remain unknown; an earlier
quote is not a replacement for those terms.

Read monetary fields such as taxes, cancellation amounts and policy fees from their
`*_money` objects. These contain integer minor units, currency, decimal places and a
display string. Deprecated numeric fields remain available for compatibility.
Percentage and night-count penalties are quantities rather than currency amounts.

The multi-room supplier integration in this preview is Nuitée. HotelBeds multi-room
booking is outside this preview's scope.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.