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,departureDateand (round trip)returnDate— exactly as on/fare-quote(the token binds them). - Idempotency is the
Idempotency-KeyHEADER (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[].travelerTypeisADULT/CHILD/INFANT, and the array must matchadults/children/infants. ACHILDorINFANTneedsdateOfBirth; everyINFANTneeds aguardian(the travelling adult’s name).- If
/bookis slow or your request times out, never book again with a new key. If you got a booking back, read itsstatus(PENDING_CONFIRMATIONmeans wait: readGET /bookings/{id}every 30 seconds). If you got no answer, send the identical request again with the SAMEIdempotency-Key: you get the first booking back, or409 BOOKING_IN_PROGRESS/IDEMPOTENT_REQUEST_IN_PROGRESSwhile it is still running (wait, then send it again). - An answer with no Kitionz
error.code(for example a504from the network) or any500counts as no answer: send the same request again with the same key. Set your HTTP timeout for/bookto 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:failureClassINFANT_PRICE_WITHDRAWN(you were quoted one, the supplier gives none now; quote again: it showsNOT_GIVEN) orINFANT_PRICE_APPEARED(you were quotedNOT_GIVEN, the supplier gives one now; quote again: it showsPRICED). 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’sfareBreakdown.infantFareis the supplier’s statement when the booking was made; since/bookrefuses any change from the quote, it is always the status you were quoted.
Example — request (with the Idempotency-Key: <your-uuid> header):
Response (trimmed) — the HTTP status is 201; decide by data.status:
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
Your Kitionz API key, sent as Authorization: Bearer keyId:secret. Create it in your Kitionz console under API → API keys.
Headers
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
The offer’s departureDate from /search — send it back unchanged (a different date → 400 OFFER_TRIP_MISMATCH).
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.
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).
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.
Response
A full persisted booking (passengers, segments, events, amounts, status).