Booking

A booking groups one or more reservations (one reservation = one unit) at the same property, with one customer and, if needed, one payment card.

Booking  BK-EUWIGPSG
 ├── Reservation RS-AAAAAAAA  (unit 1, offer X, guests …)
 └── Reservation RS-BBBBBBBB  (unit 2, offer Y, guests …)

Creating a booking

POST /v2/bookings

{
  "customer": {
    "first_name": "John", "last_name": "Doe",
    "email": "[email protected]", "phone_number": "+31612345678",
    "address_line_1": "Damrak 1", "postcode": "1012LG", "city": "Amsterdam", "country": "NL",
    "company_name": "Acme B.V."
  },
  "reservations": [
    { "offer_id": "9131b7c8-…", "guests": [ { "first_name": "John", "last_name": "Doe" }, { "first_name": "Jane", "last_name": "Doe" } ] },
    { "offer_id": "5be0e7f1-…", "guests": [ { "first_name": "Max", "last_name": "Doe" } ] }
  ],
  "comments": ["Late arrival, around 22:00"],
  "payment": { "type": "visa", "card_number": "4111111111111111", "cvv": "123",
               "card_holder": "John Doe", "expiry_month": "11", "expiry_year": "2028" }
}

Rules:

  • One reservation per unit. For a multi-unit search, send the reservations in the same order as the units in your occupancy. Respect occupancy_has_offer (Availability).
  • One property per booking. All offers must belong to the same property. The maximum number of reservations per booking is nine, but it's PMS/CRS dependent.
  • Multi-unit bookings are all-or-nothing. Either every reservation is confirmed or none is. If one unit fails at the hotel, we cancel the units that were already created.
  • Guests per reservation: at least 1, and at most the adults + children of the unit you searched for. Sending more gives the number of guests is more than allowed.
  • Offers are single-use. Once you've made a booking request with an offer, don't use it again, even if that booking failed or your request timed out (Offers).

Customer and guest data

The customer is the booker. The hotel receives the customer's email and phone as the contact for the booking, and the customer's address as the billing address for the card. Guests are the people staying.

FieldRequiredGuidance
customer.first_name, last_name, email, phone_number, address_line_1, postcode, city, countryYes—
guests[].first_name, last_nameYes—
country—Send either an ISO 3166-1 alpha-2 code (NL, GB, US), or the country's name (France)
phone_number—International format, max 14 characters (+31612345678). Some hotel systems reject longer numbers.
Names—Up to 256 characters. Where a hotel system accepts fewer. Prefer plain Latin letters: some hotel systems reject characters like Ü.
titleNoe.g. Mr, Ms
birth_dateNoYYYY-MM-DD
company_nameNoThe customer's company. Use it for invoicing details, since there is no VAT-number field. Add the VAT number in comments if the hotel needs it.
commentsNoOn the booking (sent with every reservation) or per reservation. Max 500 characters per comment. They are passed to the hotel, but special requests are not guaranteed.
loyalty_idNoThe loyalty number with the hotel chain, where supported. One per booking: most chains accept only one, so it is not per guest.
iata_codeNoYour IATA number, max 12 characters, one per booking. Send it on every booking that should carry it; hotels use it to pay travel-agent commission.
tax_remittanceNoOnly if you are registered for tax remittance in the US: SINGLE_REMITTANCE or DUAL_REMITTANCE.

Confirmation is asynchronous

A 201 from POST /bookings means we accepted the booking and are sending it to the hotel. It does not mean the hotel confirmed it. Every reservation starts as TO_BE_DELIVERED.

To find out the result, poll GET /v2/bookings/{booking_id} until every reservation has a final status.

Recommended polling:

  • Poll every 1–2 seconds.
  • Most bookings settle within 10 seconds.
  • Keep polling for up to 120 seconds. Some hotel systems need two calls of up to 30 seconds each, and multi-unit bookings take longer. Bookings taking 40–60 seconds are normal for those systems.
  • If a reservation is still TO_BE_DELIVERED after that, the reservation should be marked as failed.
  • A failed GET is not a failed booking. If GET /bookings/{id} itself returns an error (e.g. 500 or a timeout), retry it. Only the reservation status tells you the outcome. Treating a lookup error as a failure leads to the customer booking twice.
  • If POST /bookings times out on your side and you have no booking ID, don't retry with the same offer: the first request may have gone through, and the offer is now used up. Contact support with the time and guest name before rebooking.

Reservation statuses

StatusFinal?Meaning
TO_BE_DELIVEREDnoWe received the reservation and are sending it to the hotel.
CONFIRMEDyesThe hotel confirmed it. supplier_confirmation_id holds the hotel's confirmation number.
FAILEDyesThe hotel did not create the reservation. See errors.
TO_BE_CANCELLEDnoWe are sending a cancellation to the hotel (Cancellation).
CANCELLEDyesThe hotel confirmed the cancellation.
CANCELLATION_FAILEDyesThe hotel did not accept the cancellation. The reservation is still active.

Multi-unit bookings: each reservation has its own status, but they succeed or fail together. If one fails, the others end up FAILED or CANCELLED too.

Reservation errors

When a reservation fails, errors[] usually explains why. It can occasionally be empty.

"errors": [ { "code": "PRICE_CHANGED", "message": "…" } ]
CodeMeaningWhat to do
NO_AVAILABILITYThe unit sold out between search and booking.Search again.
PRICE_CHANGEDThe hotel returned a different price at booking time; nothing was booked.Search again and show the new price.
PAYMENT_ERRORThe hotel couldn't charge or validate the card (declined, insufficient funds, unsupported type, or the card expires before check-in).Use another card. Card issues are between you, the card issuer and the hotel; Katanox only passes the card on.
SUPPLIER_ERRORThe hotel rejected the booking for another reason. The message may contain the hotel's own text (e.g. invalid name or phone).Check the message; and create a new reservation.
EXTERNAL_TIMEOUTThe hotel system didn't answer in time. We don't know whether the hotel created the booking.See below.
INTERNAL_SERVER_ERRORSomething failed on Katanox's side; no hotel error implied.Retry with a fresh offer.
UPDATE_REJECTEDA modification was rejected by the hotel.—
CANCELLATION_REJECTEDA cancellation was rejected by the hotel.See Cancellation.

When the hotel times out (EXTERNAL_TIMEOUT)

The reservation is marked FAILED, but the hotel may still have processed it ("ghost booking"). The hotel then holds a reservation we don't have a confirmation number for.

  • Don't immediately rebook the same guest at the same property for the same dates. You may end up with two bookings.

Retrieving a booking

GET /v2/bookings/{booking_id} returns the booking with every reservation, its status, price, policies (a snapshot from booking time) and errors.

To fetch one reservation, use GET /v2/bookings/{booking_id}/reservations/{reservation_id}.

IDWhere you see it
booking.idBK-…, returned by POST /bookings
reservation.idRS-…, one per unit
reservation.booking_idThe BK-… the reservation belongs to
reservation.supplier_confirmation_idThe hotel's confirmation number, set once CONFIRMED

Invoices and folios

  • GET /v2/bookings/{booking_id}/invoices returns the folio data the hotel has issued for the booking (charges, payments).
  • GET /v2/bookings/{booking_id}/invoices/{invoice_id}/file returns the invoice document.

Both are only available for hotel systems that provide them, and only after the hotel has issued them (usually after check-out).