Hotel getting started
You follow a two-room example from search through booking.
In short
10 calls, in the order this page makes themFor people and agents- 1GET
/v1/hotel/capabilitiesRead supported hotel features and limits - 2POST
/v1/hotel/searchFind hotels for your stay - 3GET
/v1/hotel/content/{hotel_id}Read hotel details and reviews - 4POST
/v1/hotel/offersPrice your selected hotels - 5POST
/v1/hotel/prebookPrebook a hotel stay - 6POST
/v1/hotel/bookings/{id}/bookComplete your hotel booking - 7GET
/v1/hotel/bookings/{id}Read your hotel booking - 8GET
/v1/hotel/bookingsList your hotel bookings - 9GET
/v1/hotel/bookings/{id}/cancellation-quoteEstimate your cancellation fee - 10POST
/v1/hotel/bookings/{id}/cancelCancel your hotel booking
The same list heads this page's Markdown:/hotel/hotel-getting-started.md
You create a two-room reservation by searching, selecting an offer, assigning guests, and completing payment and booking. This walkthrough uses LiteAPI with two adults in each room. You can use the same sequence with another supported supplier, subject to its capabilities and guest requirements.
Before you begin
You need a server-side API key and a payment instrument available to the booking owner. Set BASE_URL to the gateway host for your environment and API_KEY to your key, following the gateway authentication guide. The gateway establishes your organization and uses the API-key ID as the booking owner. You do not supply internal ingress or identity headers through the gateway. Use the same key for the entire booking lifecycle.
You use /v1/hotel as the base path for every operation below. Send Content-Type: application/json for requests with a body. For example, you can read capabilities with:
curl "$BASE_URL/v1/hotel/capabilities" \
-H "x-api-key: $API_KEY"You replace the illustrative dates with future travel dates and every placeholder identifier, offer reference, cursor and token with a value from your integration. Check-out must follow check-in by no more than 99 nights. The example responses show synthetic data; they do not identify bookable inventory or usable credentials.
1. Search for two rooms
You send POST /search with one occupancy per room. Include every child's age when children are travelling. Check capabilities before selecting a supplier explicitly; the capability list describes implemented features, not availability or your routing rules.
Request:
{
"supplier": "LITEAPI",
"destination": {
"city": "Dubai",
"country_code": "AE"
},
"check_in": "2027-11-22",
"check_out": "2027-11-24",
"occupancy": [
{
"adults": 2,
"children": []
},
{
"adults": 2,
"children": []
}
],
"guest_nationality": "GB",
"guest_residence": "GB",
"currency": "USD",
"limit": 10
}Example response:
{
"data": [
{
"hotel_id": "htl_example",
"supplier_hotel_id": "lp1f2e3",
"name": "Example Marina Hotel",
"city": "Dubai",
"country": "AE",
"cheapest_price": {
"total": {
"amount": 600,
"currency": "USD"
}
}
}
],
"meta": {
"supplier": "LITEAPI",
"pagination": {
"limit": 10,
"next_cursor": "REPLACE_WITH_RETURNED_CURSOR"
}
}
}You retain the returned hotel_id and meta.supplier; each hotel also carries the supplier's own supplier_hotel_id. To continue the search, send meta.pagination.next_cursor as cursor with the original search fields; you may change limit. Stop only when next_cursor is omitted, even if a page is short or empty. A cursor preserves the supplier and search criteria, not an inventory snapshot.
You can read GET /content/{hotel_id} for property details. Search prices support comparison; you obtain a bookable offer in the next step.
2. Request and review an offer
You send POST /offers with the selected hotel ID and the same dates, occupancies and source market. You can name hotels by the supplier's IDs instead: send supplier_hotel_ids with meta.supplier as supplier, never together with hotel_ids.
Request:
{
"hotel_ids": [
"htl_example"
],
"check_in": "2027-11-22",
"check_out": "2027-11-24",
"occupancy": [
{
"adults": 2,
"children": []
},
{
"adults": 2,
"children": []
}
],
"guest_nationality": "GB",
"guest_residence": "GB",
"currency": "USD",
"max_offers_per_hotel": 5
}Example response:
{
"data": [
{
"hotel_id": "htl_example",
"supplier_hotel_id": "lp1f2e3",
"offers": [
{
"offer_reference": "REPLACE_WITH_RETURNED_OFFER_REFERENCE",
"total": {
"amount": 600,
"currency": "USD"
},
"rooms": [
{
"position": 0,
"adults": 2,
"children": [],
"room_type": "Deluxe Twin",
"board": "Room Only",
"refundable": true,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
}
},
{
"position": 1,
"adults": 2,
"children": [],
"room_type": "Deluxe Double",
"board": "Room Only",
"refundable": true,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
}
}
],
"room_type": "Deluxe Twin",
"board": "Room Only",
"refundable": true,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 300,
"currency": "USD"
}
}
],
"restrictions": []
},
"expires_at": "2027-10-01T10:15:00Z"
}
]
}
],
"meta": {
"supplier": "LITEAPI"
}
}You choose an entry from data[].offers[] and preserve its offer_reference unchanged. Submit it before expires_at. The total covers both rooms for the complete stay; you do not multiply it by the number of rooms or nights. Read rooms in occupancy order. The top-level room_type and board describe the first room. A policy on the offer covers the whole stay; a policy inside a room covers only that room. In this example, the offer policy combines both room policies. Use either the combined offer policy or the individual room policies for their respective scope; do not add both.
3. Assign guests and prebook
You send POST /prebook with a new x-idempotency-key for this intended booking. Retain that key before making the request. Name exactly one adult lead per room and preserve room order. This example names every adult and provides their types, which also satisfies WebBeds' guest naming requirement.
Request:
{
"offer_reference": "REPLACE_WITH_RETURNED_OFFER_REFERENCE",
"reference_id": "order-example",
"use_payment_sdk": false,
"contact": {
"first_name": "Alex",
"last_name": "Morgan",
"email": "alex@example.com",
"phone": "+447700900123"
},
"rooms": [
{
"guests": [
{
"first_name": "Alex",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": true
},
{
"first_name": "Sam",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": false
}
]
},
{
"guests": [
{
"first_name": "Jamie",
"last_name": "Lee",
"type": "ADULT",
"is_lead": true
},
{
"first_name": "Taylor",
"last_name": "Lee",
"type": "ADULT",
"is_lead": false
}
]
}
]
}You can save the request as prebook.json and send it from your server:
curl "$BASE_URL/v1/hotel/prebook" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "x-idempotency-key: $PREBOOK_IDEMPOTENCY_KEY" \
--data-binary @prebook.jsonExample response:
{
"data": {
"id": "bkg_example",
"reference_id": "order-example",
"status": "READY_FOR_COMPLETE",
"hotel": {
"id": "htl_example",
"name": "Example Marina Hotel",
"address": "Example Avenue, Dubai, AE"
},
"check_in": "2027-11-22",
"check_out": "2027-11-24",
"total": {
"amount": 600,
"currency": "USD"
},
"created_at": "2027-10-01T10:01:00Z",
"updated_at": "2027-10-01T10:01:01Z",
"confirmed_at": null,
"canceled_at": null,
"payments": [],
"cancellations": [],
"hotel_confirmation_code": null,
"hotel_remarks": null,
"offer_expires_at": "2027-10-01T10:15:00Z",
"due_at_property": null,
"cancellation_policy": null,
"contact": {
"first_name": "Alex",
"last_name": "Morgan",
"email": "alex@example.com",
"phone": "+447700900123"
},
"loyalty": null,
"rooms": [
{
"id": "room_example1",
"position": 0,
"name": "Deluxe Twin",
"board": "ROOM_ONLY",
"board_name": "Room Only",
"adults": 2,
"children": [],
"total": {
"amount": 300,
"currency": "USD"
},
"due_at_property": null,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
},
"promotions": null,
"supplier_reference_number": null,
"hotel_confirmation_code": null,
"canceled_at": null,
"guests": [
{
"id": "guest_example11",
"first_name": "Alex",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": true
},
{
"id": "guest_example12",
"first_name": "Sam",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": false
}
]
},
{
"id": "room_example2",
"position": 1,
"name": "Deluxe Double",
"board": "ROOM_ONLY",
"board_name": "Room Only",
"adults": 2,
"children": [],
"total": {
"amount": 300,
"currency": "USD"
},
"due_at_property": null,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
},
"promotions": null,
"supplier_reference_number": null,
"hotel_confirmation_code": null,
"canceled_at": null,
"guests": [
{
"id": "guest_example21",
"first_name": "Jamie",
"last_name": "Lee",
"type": "ADULT",
"is_lead": true
},
{
"id": "guest_example22",
"first_name": "Taylor",
"last_name": "Lee",
"type": "ADULT",
"is_lead": false
}
]
}
]
}
}You save data.id and continue only when data.status is READY_FOR_COMPLETE. Review the returned total, due_at_property, cancellation_policy and room terms with your customer; prebook can return updated prices or terms. The room totals in this example are 300 USD each. The booking has no separate combined policy; review the policies on both rooms. A null due_at_property means the amount is unknown, not zero. Prebook does not confirm a reservation.
4. Complete payment and booking
You send POST /bookings/{id}/book with your saved booking ID and payment instrument ID.
Request:
{
"payment_instrument_id": "REPLACE_WITH_YOUR_PAYMENT_INSTRUMENT_ID"
}Example response after confirmation and capture:
{
"data": {
"id": "bkg_example",
"reference_id": "order-example",
"status": "CONFIRMED",
"hotel": {
"id": "htl_example",
"name": "Example Marina Hotel",
"address": "Example Avenue, Dubai, AE"
},
"check_in": "2027-11-22",
"check_out": "2027-11-24",
"total": {
"amount": 600,
"currency": "USD"
},
"created_at": "2027-10-01T10:01:00Z",
"updated_at": "2027-10-01T10:03:00Z",
"confirmed_at": "2027-10-01T10:03:00Z",
"canceled_at": null,
"payments": [
{
"id": "pay_example",
"status": "CAPTURED",
"amount": {
"amount": 600,
"currency": "USD"
},
"payment_method": {
"type": "CARD",
"card": {
"brand": "VISA",
"last4": "4242",
"funding": "CREDIT",
"wallet": null
}
},
"created_at": "2027-10-01T10:02:00Z"
}
],
"cancellations": [],
"hotel_confirmation_code": null,
"hotel_remarks": null,
"offer_expires_at": "2027-10-01T10:15:00Z",
"due_at_property": null,
"cancellation_policy": null,
"contact": {
"first_name": "Alex",
"last_name": "Morgan",
"email": "alex@example.com",
"phone": "+447700900123"
},
"loyalty": null,
"rooms": [
{
"id": "room_example1",
"position": 0,
"name": "Deluxe Twin",
"board": "ROOM_ONLY",
"board_name": "Room Only",
"adults": 2,
"children": [],
"total": {
"amount": 300,
"currency": "USD"
},
"due_at_property": null,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
},
"promotions": null,
"supplier_reference_number": null,
"hotel_confirmation_code": null,
"canceled_at": null,
"guests": [
{
"id": "guest_example11",
"first_name": "Alex",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": true
},
{
"id": "guest_example12",
"first_name": "Sam",
"last_name": "Morgan",
"type": "ADULT",
"is_lead": false
}
]
},
{
"id": "room_example2",
"position": 1,
"name": "Deluxe Double",
"board": "ROOM_ONLY",
"board_name": "Room Only",
"adults": 2,
"children": [],
"total": {
"amount": 300,
"currency": "USD"
},
"due_at_property": null,
"cancellation_policy": {
"version": 1,
"refundable": true,
"deadline": "2027-11-20T00:00:00Z",
"penalties": [
{
"from": "2027-11-20T00:00:00Z",
"type": "AMOUNT",
"amount": {
"amount": 150,
"currency": "USD"
}
}
],
"restrictions": []
},
"promotions": null,
"supplier_reference_number": null,
"hotel_confirmation_code": null,
"canceled_at": null,
"guests": [
{
"id": "guest_example21",
"first_name": "Jamie",
"last_name": "Lee",
"type": "ADULT",
"is_lead": true
},
{
"id": "guest_example22",
"first_name": "Taylor",
"last_name": "Lee",
"type": "ADULT",
"is_lead": false
}
]
}
]
}
}You treat CONFIRMED as reservation confirmation. An HTTP 200 alone does not establish the booking state. A null hotel confirmation code can coexist with a confirmed supplier reservation. Payment status records the last stored payment outcome; a confirmed booking can still require payment recovery.
Use the Payment SDK instead
You choose the SDK path before prebook by setting use_payment_sdk to true. The fresh prebook response additionally contains meta.payment_sdk.token and an initiated payment. Protect the token and pass it to your Payment SDK integration. After authorization completes, send an empty JSON object to POST /bookings/{id}/book, without payment_instrument_id. The endpoint reference includes a complete SDK prebook response example.
You cannot retrieve the token through a repeated prebook or a booking read. If the response or token is lost, recover the same booking and follow Hotel retries and idempotency before replacing the checkout. SDK authorization alone does not confirm the hotel reservation.
5. Read the reservation and recover interrupted calls
You read GET /bookings/{id} with the same owner context. If book times out or returns an unknown result, read this booking instead of creating a replacement purchase. Use Hotel booking lifecycle to interpret the status and Hotel retries and idempotency for bounded polling and escalation.
You can also locate bookings with GET /bookings?reference_id=order-example&status=CONFIRMED. References are not unique; inspect every matching page and retain each booking ID. Stop when meta.has_more is false. The booking list omits guest details and payment cards; read an individual booking for those details.
6. Preview and request cancellation
You read GET /bookings/{id}/cancellation-quote before presenting a cancellation fee. Inspect available, source and checked_at, as explained in Hotel cancellations and recovery. A preview is advisory and does not reserve a fee.
You send POST /bookings/{id}/cancel without a body to request cancellation of all remaining rooms. Read the booking while cancellation continues. Room outcomes and cancellation history establish what was released; a refund amount records intent, not settlement. The endpoint reference includes in-progress, canceled, partially canceled and unknown-refund examples.