Skip to navigation

6 · Book

Place a booking.

What: places the booking. Requires the quoteToken from /fare-quote; the supplier-quoted price is taken from the signed token, so a tenant can’t book a different price than was quoted.

When: after a successful /fare-quote, within the token’s validity.

Before / After: /fare-quote → here → read the booking’s status (and /bookings/{id}/ticket if it is HELD).

Gotchas

  • Send the offer’s trip back — tripType, departureDate and (round trip) returnDate — exactly as on /fare-quote (the token binds them).
  • Idempotency is the Idempotency-Key HEADER (required). Persist it and reuse the same value on retries — the booking is reserved before the supplier call, so a retry returns the same booking instead of charging twice. There is no body idempotency field.
  • passengers[].travelerType is ADULT / CHILD / INFANT, and the array must match adults/children/infants. A CHILD or INFANT needs dateOfBirth; every INFANT needs a guardian (the travelling adult’s name).
  • If /book is slow or your request times out, never book again with a new key. If you got a booking back, read its status (PENDING_CONFIRMATION means wait: read GET /bookings/{id} every 30 seconds). If you got no answer, send the identical request again with the SAME Idempotency-Key: you get the first booking back, or 409 BOOKING_IN_PROGRESS / IDEMPOTENT_REQUEST_IN_PROGRESS while it is still running (wait, then send it again).
  • An answer with no Kitionz error.code (for example a 504 from the network) or any 500 counts as no answer: send the same request again with the same key. Set your HTTP timeout for /book to at least 90 seconds; a slow supplier can take more than a minute.
  • Just before booking, Kitionz asks the supplier for the fare again and checks it the same way as /fare-quote. A broken answer → 422 FARE_QUOTE_UNUSABLE. An infant price that changed since your quote → 409 FARE_RECHECK_FAILED: failureClass INFANT_PRICE_WITHDRAWN (you were quoted one, the supplier gives none now; quote again: it shows NOT_GIVEN) or INFANT_PRICE_APPEARED (you were quoted NOT_GIVEN, the supplier gives one now; quote again: it shows PRICED). All are definite: nothing was booked or charged.
  • You never send an amount. When the quote said infantFare.status: NOT_GIVEN, the booking is made at the supplier’s total (adults and children) and your own infant charge stays with you. The booking’s fareBreakdown.infantFare is the supplier’s statement when the booking was made; since /book refuses any change from the quote, it is always the status you were quoted.

Example — request (with the Idempotency-Key: <your-uuid> header):

{
"supplierOfferRef": "floffer_9x2k7q",
"quoteToken": "eyJhbGci…",
"adults": 1, "tripType": "ONE_WAY", "departureDate": "2027-01-15",
"originCode": "DEL", "destCode": "BOM",
"booker": { "name": "Asha Rao", "email": "asha@example.com", "phone": "+919800000000" },
"passengers": [ { "title": "Ms", "firstName": "Asha", "lastName": "Rao", "travelerType": "ADULT" } ]
}

Response (trimmed) — the HTTP status is 201; decide by data.status:

{ "data": { "id": "bkg_7f3a92", "status": "CONFIRMED", "pnr": "AB12CD", "supplier": { "name": "Airnatt Holidays", "website": "https://airnatt.com", "supportPhone": "+91 99999 00000", "supportEmail": "help@airnatt.com" }, "returnSupplier": null } }

supplier names who sold the flight (the real seller behind a marketplace), with the support contacts Kitionz holds — on every booking from the moment it exists. returnSupplier is always null (one seller per booking); it will be removed in a later version.

Authentication

AuthorizationBearer

Your Kitionz API key, sent as Authorization: Bearer keyId:secret. Create it in your Kitionz console under API → API keys.

Headers

Idempotency-KeystringRequiredformat: "^[a-zA-Z0-9_-]{1,255}$"

Unique key per logical write; reuse the SAME value on retries to get the original result instead of a duplicate side effect (ADR-0022).

Request

This endpoint expects an object.
supplierOfferRefstringRequired1-120 characters
adultsintegerRequired1-9
departureDatestringRequired

The offer’s departureDate from /search — send it back unchanged (a different date → 400 OFFER_TRIP_MISMATCH).

originCodestringRequired2-10 characters
destCodestringRequired2-10 characters
passengerslist of objectsRequired
quoteTokenstringRequired40-8192 characters
sourceCodestringOptional2-50 characters

Leave it out: supplierOfferRef already names the supplier. Only an organisation shown suppliers before booking may send it, and it must then match the offer; for everyone else it is refused with SOURCE_CODE_NOT_ACCEPTED.

childrenintegerOptional0-9Defaults to 0
infantsintegerOptional0-9Defaults to 0
tripTypeenumOptional

The offer’s tripType from /search. May be left out: the offer’s own trip type is used. When sent it must be the offer’s (another → 400 OFFER_TRIP_MISMATCH).

Allowed values:
returnDatestringOptional

Round trip only: the offer’s returnDate from /search, sent only with tripType ROUND_TRIP. May be left out (the offer fixes it); when sent, send it on /fare-quote and /book alike.

bookerobjectOptionalDefaults to {}
selectedSeatslist of objectsOptional
selectedSSRslist of objectsOptional
bookingModeenumOptionalDefaults to LIVE
Allowed values:
formOfPaymentobjectOptional
privateFareCodesobjectOptional
externalReferencestringOptionalformat: "^[^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]*$"<=120 characters

Response

Success
successboolean
statusCodedouble
dataobject

A full persisted booking (passengers, segments, events, amounts, status).

metaobject

Errors

502
Bad Gateway Error