> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.kitionz.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.kitionz.com/_mcp/server.

# Flights

Every Flight API call, in the order you make them: the booking flow first, then the calls you make after booking, then the extras.

## Booking flow

The 8 calls, in the order you make them.

| # | Call                                        | Method | Path                               | What it does                          |
| - | ------------------------------------------- | ------ | ---------------------------------- | ------------------------------------- |
| 1 | [Origins](/flights/origins)                 | POST   | `/v1/flights/origins`              | List origin airports                  |
| 2 | [Destinations](/flights/destinations)       | POST   | `/v1/flights/destinations`         | List destinations for an origin       |
| 3 | [Available dates](/flights/available-dates) | POST   | `/v1/flights/availability`         | List available dates for a route      |
| 4 | [Search](/flights/search)                   | POST   | `/v1/flights/search`               | Search flights                        |
| 5 | [Fare quote](/flights/fare-quote)           | POST   | `/v1/flights/fare-quote`           | Re-price an offer & get a quote token |
| 6 | [Book](/flights/book)                       | POST   | `/v1/flights/book`                 | Place a booking                       |
| 7 | [Get a booking](/flights/get-a-booking)     | GET    | `/v1/flights/bookings/{id}`        | Get a booking                         |
| 8 | [Cancel](/flights/cancel)                   | POST   | `/v1/flights/bookings/{id}/cancel` | Cancel a booking                      |

## After booking

Find your bookings, follow one until it settles, and finish a hold, a request booking or a refund. Holds, ticketing and refunds work only with Kitionz Test Air today (see Going Live below).

| Call                                    | Method | Path                                | What it does                                    |
| --------------------------------------- | ------ | ----------------------------------- | ----------------------------------------------- |
| [List bookings](/flights/list-bookings) | GET    | `/v1/flights/bookings`              | List your bookings                              |
| [Poll status](/flights/poll-status)     | GET    | `/v1/flights/bookings/{id}/status`  | Poll a booking’s async status                   |
| [Refresh](/flights/refresh)             | POST   | `/v1/flights/bookings/{id}/refresh` | Refresh a booking from the supplier             |
| [Ticket a hold](/flights/ticket-a-hold) | POST   | `/v1/flights/bookings/{id}/ticket`  | Ticket a HELD booking                           |
| [Submit PNR](/flights/submit-pnr)       | POST   | `/v1/flights/bookings/{id}/fulfil`  | Submit the PNR for an offline (request) booking |
| [Refund](/flights/refund)               | POST   | `/v1/flights/bookings/{id}/refund`  | Request a refund                                |

## Extras

What a fare allows, where a passenger can sit, and which suppliers your key reaches. Fare rules and seat maps work only with Kitionz Test Air today.

| Call                                 | Method | Path                     | What it does                         |
| ------------------------------------ | ------ | ------------------------ | ------------------------------------ |
| [Fare rules](/flights/fare-rules)    | GET    | `/v1/flights/fare-rules` | Get fare rules for an offer          |
| [Seat map](/flights/seat-map)        | GET    | `/v1/flights/seat-map`   | Get the seat map for an offer        |
| [Your suppliers](/flights/suppliers) | GET    | `/v1/flights/suppliers`  | List the suppliers your searches use |

## When to take your customer's money

Take your customer's payment just before **Book** (the quote holds about 15 minutes). Then act on the booking's `status`:

* `CONFIRMED` or `HELD` → keep the payment.
* `FAILED`, or any `4xx` from Book → refund it: nothing was booked.
* `RESERVED` or `PENDING_CONFIRMATION` (`nextAction.code` is `WAIT`), a `5xx`, or no answer → **keep it**: do not refund and do not book again until the booking reads `CONFIRMED` or `FAILED`. Most settle within 10 minutes; still pending after 20 minutes, contact Kitionz support.

Kitionz takes no money for a booking: you pay the seller from your own account with that seller.

## Which id to keep

| From             | Keep                    | For                                                                                                                                                    |
| ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Search           | `offerId` (`floffer_…`) | Fare quote and Book, until the offer's `expiresAt` (about 15 minutes)                                                                                  |
| Fare quote       | `quoteToken`            | Book, until `quoteTokenExpiresAt`; one booking per quote                                                                                               |
| You, before Book | your `Idempotency-Key`  | sending Book again safely after a timeout                                                                                                              |
| You, on Book     | `externalReference`     | your own order number: if you lose Book's answer, list your bookings with it to find the booking                                                       |
| Book             | `id` (`bkg_…`)          | every call after booking — key your orders on it                                                                                                       |
| Book             | `pnr`                   | the airline's booking code, for check-in and the airline's website; it can arrive minutes after Book, and a held booking has one before it is ticketed |
| Book             | `supplierReference`     | the seller's own booking number: quote it to the seller's support                                                                                      |

Key your orders on `id`, never on the PNR. Kitionz does not return e-ticket numbers or the ticket document: get them from the seller named in the booking's `seller`.

## Times and money

* **Times.** A flight's `departureTime` and `arrivalTime` are the airport's local clock with its UTC offset (`2027-01-15T06:00:00+05:30`), and each flight's `origin.timezone` / `destination.timezone` name the zone. Show the clock time as written; never convert a flight time to your server's or your user's zone. `departureDate` and `returnDate` are local dates at the departure airport. Kitionz's own times (`expiresAt`, `quoteTokenExpiresAt`, `nextAction.deadlineAt`, `createdAt`) are UTC, ending in `Z`.
* **Money.** Every amount is Indian rupees (`currency: INR`): a number with up to two decimals, so `4511.86` is ₹4,511.86 — not paise. A gateway that takes paise needs the amount × 100, worked out with exact decimals. Charge from the fare quote's `price.totalAmount`; never add up the parts yourself. Offers, fare quotes and bookings carry the same `price` block.
* **Per-passenger prices.** `price.passengerFares` has one row per passenger type (`passengerType`, `count`): `total` is the price of **all** passengers of that type together and `perPerson` is one passenger's, to the paisa. When every row states a total, the rows add up to `totalAmount`. Charge `totalAmount`, never a sum of `perPerson`.

## Passengers

* **Types.** `ADULT` is 12 or older, `CHILD` 2–11, `INFANT` under 2, by age on the date of the last flight (the return flight on a round trip). A passenger whose age does not fit the type answers `422 PASSENGER_FIELD_REQUIRED` ("… Search again with this passenger as a child."): search again with that count. Search, quote and book with the same `adults`, `children` and `infants`: another party answers `400 PASSENGER_COUNTS_CHANGED`. At most 9 adults and children in one booking.
* **Infants.** Each infant sits on an adult's lap: send `guardianPassengerIndex`, the position in `passengers` (0 = the first) of that `ADULT`. One infant per adult. An infant who turns 2 before the return flight travels as a `CHILD`.
* **Names.** Send `firstName` and `lastName` for everyone. A traveller with one name: send it as both.
* **Titles.** `Mr`, `Mrs` or `Ms` for adults; `Master` (boy) or `Miss` (girl) for children and infants. Kitionz sets `gender` from the title; with any other title (`Dr`, `Prof`), send `gender` (`MALE` or `FEMALE`).
* **Date of birth.** A `CHILD` or `INFANT` always needs `dateOfBirth`. A domestic `ADULT` sent without one is sent to the seller with 1 January of (this year − 20), because some sellers refuse a booking without a date of birth. The booking answers `dateOfBirth: null` with `dateOfBirthDefaulted: true` for that passenger, so you never show a date nobody gave.
* **Contact.** The seller receives **your organisation's registered email and mobile** as the booking contact, not `booker`. E-tickets, schedule changes and cancellations from the seller or the airline come to you: pass them on to your traveller. `booker` is your record of who made the booking; Kitionz sends `booker.name` as the contact name. Phone numbers: an Indian mobile, 10 digits, `+91` optional.
* **International trips.** Every offer has `isInternational` (true when a flight crosses a border, or when Kitionz cannot tell) and `requiredPassengerFields.fields`, each `MANDATORY` or `OPTIONAL`. On an international offer every passenger needs `dateOfBirth`, `passportNumber`, `passportExpiryDate` and `nationality`, and the passport must be valid at least 6 months after the last flight. Send countries as two-letter codes (`IN`, not `Indian`). Leave `passportIssuingCountry` out unless the passport was issued by another country than `nationality`. Collect all of this **before you take payment**: a missing field answers `422 PASSENGER_FIELD_REQUIRED`, a passport that expires too soon `422 PASSPORT_EXPIRY_TOO_SOON`; `error.details.invalidFields` lists every passenger and field, and nothing is sent to the seller.
* **Test is lenient.** Kitionz Test Air accepts any title, phone or country. Live sellers refuse a detail they cannot take with `400 BOOK_PASSENGER_TITLE_UNSUPPORTED`, `BOOK_CONTACT_PHONE_UNSUPPORTED` or `BOOK_PASSENGER_COUNTRY_UNSUPPORTED`: follow these rules in Test too.

## Going Live

* **KYC.** Your organisation's KYC must be approved before Live flight calls work; until then they answer `403 KYC_NOT_APPROVED`. Test needs none.
* **IP allow-list.** Put your server's IP address on the Live key's allow-list (kitionz.com → **API → API keys**). A call from another address answers `403 IP_NOT_ALLOWED`. Test keys have no allow-list.
* **Suppliers.** A supplier serves your Live traffic only after you request go-live for it on kitionz.com → **Suppliers** and Kitionz approves it.
* **Money.** Kitionz takes no money for a booking. You pay each seller from your own account with that seller: a low balance answers `402 SUPPLIER_INSUFFICIENT_BALANCE` (nothing booked; top up with the seller, then quote and book again). For a request booking you book and pay on the seller's own site.
* **What only Test does today.** Holds, ticketing, cancel, refund, fare rules and seat maps work only with Kitionz Test Air. Cancel a Live booking with the seller named in the booking's `seller`: the seller refunds you on their own terms, and the Kitionz booking stays `CONFIRMED`.
* **After booking.** Kitionz does not watch confirmed bookings for airline changes yet, and sends no webhook for them: sellers and airlines send changes to your registered email and mobile. Watch each booked flight with Flight Status (`POST /v1/flight-status/monitors`) and refresh the booking the day before departure.
* **Values.** Live sellers often leave values not stated (`null`, `NOT_GIVEN`). Kitionz Test Air is built to look like them, so a screen that shows "Not stated" in Test should hold in Live.

## Renamed fields

These pages use only the new names. “The next release” is the next Flight API update that removes the old names. It has no date yet. Move to the new names now: until then both work, and sending an old and a new name with different values is `400 VALIDATION_ERROR`.

### Requests, renamed on 2026-10-27

| Old name                    | New name                                                                                                            | Sent on                                        |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| `supplierOfferRef`          | `offerId`                                                                                                           | Fare quote, Book, Fare rules, Seat map         |
| `passengers[].travelerType` | `passengers[].passengerType`                                                                                        | Book                                           |
| `passengers[].guardian`     | `passengers[].guardianPassengerIndex` (was the adult's name; now the adult's position in passengers, 0 = the first) | Book                                           |
| `bookingMode: "LIVE"`       | `bookingMode: "INSTANT"`                                                                                            | Book                                           |
| `sources`                   | `supplierCodes`                                                                                                     | Search, Origins, Destinations, Available dates |
| `sourceCode`                | `supplierCode` (the filter only; bookings still carry sourceCode)                                                   | List bookings, Fare rules, Seat map            |
| `fromDate / toDate`         | `departureFrom / departureTo`                                                                                       | List bookings                                  |

Not needed: `originCode`, `destCode` on Book (Kitionz takes the route from the offer). No longer accepted (`400`): `selectedSeats`, `selectedSSRs`, `formOfPayment`, `privateFareCodes`, `passengers[].frequentFlyer` on Book, and `departureDate` on Fare rules and Seat map.

### Answers, renamed on 2026-10-28

Every answer carries the new name beside the old one, with the same value. The next release removes the old one: read the new names now.

| Old name                                                          | New name                                                                                                                           | In                                                                                                          |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `supplierOfferRef`                                                | `offerId`                                                                                                                          | Search offer                                                                                                |
| `pricing`                                                         | `price` (one block with every part, the same on the booking)                                                                       | Search offer, Fare quote                                                                                    |
| `pricing.perPax.adult / child / infant`                           | `price.passengerFares[]` (one row per passengerType, with count, perPerson, total, baseFare, taxes)                                | Search offer, Fare quote                                                                                    |
| `pricing.infantFare`                                              | `price.infantFare`                                                                                                                 | Search offer, Fare quote                                                                                    |
| `fareBreakdown`                                                   | `price`                                                                                                                            | Booking                                                                                                     |
| `fareBreakdown.perPax[].perHeadTotal`                             | `price.passengerFares[].perPerson` (perPerson is to the paisa; perHeadTotal rounds to whole rupees — switch every read at once)    | Booking                                                                                                     |
| `totalAmount / currency`                                          | `price.totalAmount / price.currency`                                                                                               | Booking, List bookings                                                                                      |
| `booking.viaSupplierApi`                                          | `booking.requestBooking` (true where viaSupplierApi was false; always present, read bookable first)                                | Search offer                                                                                                |
| `supplier`                                                        | `seller`                                                                                                                           | Booking (and Search offer, when your organisation sees suppliers before booking)                            |
| `supplierName`                                                    | `seller.name`                                                                                                                      | List bookings                                                                                               |
| `sourceCode`                                                      | `supplierCode`                                                                                                                     | Booking, List bookings (and Search offer, Fare quote, when your organisation sees suppliers before booking) |
| `returnSupplier`                                                  | `(none)` (always null; removed)                                                                                                    | Booking                                                                                                     |
| `policy.refundPolicy / policy.changePolicy`                       | `policy.refund / policy.change`                                                                                                    | Search offer, Booking                                                                                       |
| `originCode / destCode`                                           | `origin.iataCode / destination.iataCode` (origin and destination are airport objects: iataCode, name, city, countryCode, timezone) | legs, flights, Booking, List bookings                                                                       |
| `originName / destName`                                           | `origin.name / destination.name`                                                                                                   | legs, flights                                                                                               |
| `departureTimezone / arrivalTimezone`                             | `origin.timezone / destination.timezone`                                                                                           | legs, flights                                                                                               |
| `originTerminal / destinationTerminal`                            | `departureTerminal / arrivalTerminal`                                                                                              | flights                                                                                                     |
| `marketingCarrier.code`                                           | `marketingCarrier.iataCode`                                                                                                        | Search offer flights                                                                                        |
| `airlineCode / airlineName / flightNumber`                        | `marketingCarrier.iataCode / name / flightNumber`                                                                                  | Booking flights                                                                                             |
| `technicalStops[].airportCode / airportName`                      | `technicalStops[].airport.iataCode / name`                                                                                         | flights                                                                                                     |
| `cabin (offer, booking, fareFamily) / cabinClass (legs, flights)` | `segments[].cabin` (read each flight's cabin)                                                                                      | Search offer, Booking                                                                                       |
| `requiredPassengerFields.international`                           | `isInternational`                                                                                                                  | Search offer                                                                                                |
| `passengers[].travelerType`                                       | `passengers[].passengerType`                                                                                                       | Booking                                                                                                     |
| `passengers[].guardian`                                           | `passengers[].guardianPassengerIndex` (the adult's position in passengers, not their name)                                         | Booking                                                                                                     |
| `airportName / isInternational`                                   | `name / hasInternationalFlights`                                                                                                   | airports (Origins, Destinations, airport search)                                                            |

Not renamed yet (the next release changes these too):

* Bookings show `bookingMode: "LIVE"` for a booking made with `INSTANT`, and the fare quote's `eligibility.bookingModesSupported` says `LIVE` for what `/book` calls `INSTANT`.
* Baggage rows use `paxType` `ADT`, `CHD`, `INF` for `ADULT`, `CHILD`, `INFANT`.
* Search `data.meta` supplier lists (`suppliersFailed`, …) and `GET /v1/flights/suppliers` rows still name the supplier `sourceCode`.
* Webhook booking events (`flight_booking.confirmed`, `flight_booking.rejected`) still name the seller `supplier` and `returnSupplier`.

## Try the calls on these pages

Each call has a **Try it** button. Choose the **Test** address and enter your Test key as `keyId:secret`. Never enter a Live key on a website.

## Use Postman

Prefer Postman? Download the [collection](https://kitionz.com/postman/kitionz-flight-api.postman_collection.json) and the [Test environment](https://kitionz.com/postman/kitionz-test.postman_environment.json), import both (**File → Import**), fill in `keyId` and `secret`, and send the calls in order. The collection holds the booking flow; each call stores what the next one needs.

Every example answer here was recorded from the real API on 2026-10-28, in Test, against Kitionz Test Air. Live answers have the same shape: Test Air is built to look like a Live seller.