> 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 reference

The rules that apply to many Flight API calls. Each call's page links here. Every call is on the [Flights overview](/flights/overview).

## Trip kinds

* A **one-way** offer has `tripType: "ONE_WAY"` and one leg.
* A **round trip** has `tripType: "ROUND_TRIP"`, two legs, one price for both ways and a fixed `returnDate`. Book it as one offer; never join two one-way offers.
* On [Search](/flights/search), leave `tripType` out to get every kind, each offer labelled. `ONE_WAY` returns one-way offers only, `ROUND_TRIP` round trips only.
* [Origins](/flights/origins) and [Destinations](/flights/destinations) say which kinds leave from each airport (`tripTypes`), and [Available dates](/flights/available-dates) says it for each day.

## Lists and Search

* **Another airport of the same city.** An offer can fly from or to another airport of the city you searched: `DEL` can return `HDO`, `BOM` `NMI`, `GOI` `GOX`, and `DXB` `SHJ` or `AUH`. Show the airports in each offer's `legs`, never the code you searched.
* **Suppliers without lists.** Origins, Destinations and Available dates show only what suppliers publish in their route and date lists. Suppliers without such lists are searched on every route and every day, so Search can find flights those calls do not list. Do not build a closed drop-down from them.
* **Lists are not seats.** A listed airport or day comes from the suppliers' own lists. Search asks the suppliers live, so a listed day can still have no seats.

## Empty answers

An empty list is a `200`, not an error. The outer `meta.diagnostics` says why. For example:

| `code`                                                  | Meaning                                                        | What to do                     |
| ------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------ |
| `UNKNOWN_AIRPORT`                                       | Kitionz does not know an airport code you sent.                | Check the code.                |
| `NO_RESULTS_FOR_QUERY`                                  | Your suppliers had nothing for this route and date.            | Try another date.              |
| `FILTERS_REMOVED_ALL_OFFERS`                            | Your suppliers answered, and your filters removed every offer. | Loosen your filters.           |
| `NO_FLIGHT_SUPPLIERS`, `SUPPLIER_DISABLED_BY_TENANT`, … | A supplier is not set up for your key.                         | Follow `message` and `fixUrl`. |

Treat a code you do not know as information only.

## Supplier lists in answers

Most organisations see the supplier only after booking. Their answers have empty supplier lists and `supplierDisclosure: "AFTER_BOOKING"`: Origins, Destinations and Available dates in `meta.suppliers`; Search in `data.meta` (`suppliersCalled`, `suppliersSucceeded`, `suppliersFailed`, `suppliersSkipped`, `suppliersExcluded`), with the totals in `data.meta.supplierCounts`. A supplier that fails never fails the whole call: the others still answer.

## Booking status and next action

Every booking has `status` and `nextAction`. Do what `nextAction.code` says.

| `status`                                    | Means                                             | `nextAction.code`                                                                     |
| ------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `RESERVED`, `PENDING_CONFIRMATION`          | Not final. The booking may exist at the supplier. | `WAIT`: read the booking again after `nextAction.pollAfterSeconds`. Never book again. |
| `HELD`                                      | Seats held, not ticketed.                         | `ISSUE_TICKET` before `nextAction.deadlineAt`.                                        |
| `PENDING_FULFILMENT`                        | A request. Nothing is booked yet.                 | `SUBMIT_PNR` before `nextAction.deadlineAt`.                                          |
| `CONFIRMED`                                 | Booked.                                           | `NONE`                                                                                |
| `FAILED`                                    | Not booked, nothing charged. `failure` says why.  | `SEARCH_AGAIN`                                                                        |
| `CANCELLED`                                 | Cancelled, or a request withdrawn or lapsed.      | `NONE`                                                                                |
| `CANCELLED_BY_SUPPLIER`, `SCHEDULE_CHANGED` | The seller cancelled or changed it.               | `CONTACT_SUPPLIER`                                                                    |

Most pending bookings settle within 10 minutes. Still pending after 20 minutes: contact Kitionz support with the booking `id`. What to do with your customer's money in each status is on the [Flights overview](/flights/overview).

## 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. Fare quote and Book are for the party you searched with: leave `adults`, `children` and `infants` out, or send the same numbers; other numbers answer `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.** `lastName` is optional in the API, but most sellers refuse a booking without it: 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.email`. E-tickets, schedule changes and cancellations from the seller or the airline come to you: pass them on to your traveller. `booker.phone` is sent only when your organisation has no mobile on record, and some sellers receive `booker.name` as the contact name; otherwise `booker` is your record of who made the booking. 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.

## 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`.

## Test every outcome

In Test, nothing is booked for real: each Kitionz Test Air offer rehearses one outcome. Search a Test Air route, then pick the offer whose `fareFamily.code` is the outcome you want. Several offers carry `TEST_CONFIRM` (a second seller, and the shapes Live sellers send): all book like it. Round-trip packages leave on fewer days and offer only the outcomes marked in the last column.

| `fareFamily.code`           | What happens                                                                                                                                                                   | Round-trip packages |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------- |
| `TEST_CONFIRM`              | Book answers `CONFIRMED` with a PNR.                                                                                                                                           | Yes                 |
| `TEST_SLOW_CONFIRM`         | Book answers `PENDING_CONFIRMATION` (`nextAction.code` is `WAIT`). Get a booking reads `CONFIRMED` about 2 minutes later.                                                      | Yes                 |
| `TEST_SLOW_FAIL`            | Book answers `PENDING_CONFIRMATION` (`nextAction.code` is `WAIT`). Get a booking reads `FAILED` about 2 minutes later.                                                         | —                   |
| `TEST_TIMEOUT_BOOKED`       | Book answers `PENDING_CONFIRMATION` with no `supplierReference`: the supplier gave no answer. Kitionz settles it within about 10 minutes, and Get a booking reads `CONFIRMED`. | —                   |
| `TEST_TIMEOUT_NOT_BOOKED`   | Book answers `PENDING_CONFIRMATION` with no `supplierReference`: the supplier gave no answer. Kitionz settles it within about 10 minutes, and Get a booking reads `FAILED`.    | —                   |
| `TEST_SOLD_OUT`             | Book answers `201` with `status: "FAILED"` and a `failure`. Nothing is booked.                                                                                                 | Yes                 |
| `TEST_SUPPLIER_ERROR`       | Book answers `201` with `status: "FAILED"` and a `failure`. Nothing is booked.                                                                                                 | —                   |
| `TEST_PRICE_CHANGE`         | Fare quote answers `priceChanged: true` with a higher `price.totalAmount`. Book at the new price confirms.                                                                     | Yes                 |
| `TEST_HOLD`                 | Book with `bookingMode: "HOLD"` answers `HELD`, and Ticket a hold answers `CONFIRMED`. Without `HOLD`, Book confirms at once.                                                  | —                   |
| `TEST_CANCEL_REFUSED`       | Book answers `CONFIRMED`, and Cancel answers `422 CANCEL_REFUSED`.                                                                                                             | —                   |
| `TEST_OFFER_GONE`           | Fare quote answers `502 SUPPLIER_OFFER_NOT_FOUND`. Nothing can be booked.                                                                                                      | —                   |
| `TEST_SUPPLIER_BALANCE_LOW` | Fare quote answers `402 SUPPLIER_INSUFFICIENT_BALANCE`. Nothing can be booked.                                                                                                 | —                   |

An offer with `booking.requestBooking: true` (Kitionz Test Portal) rehearses a request booking: Book answers `PENDING_FULFILMENT`, and [Submit PNR](/flights/submit-pnr) with a PNR such as `TESTA7K2Q9` confirms it.

## Errors every call can return

| HTTP     | `code`                                  | What to do                                                             |
| -------- | --------------------------------------- | ---------------------------------------------------------------------- |
| 400      | `VALIDATION_ERROR`                      | Fix the fields in `error.details.invalidFields`.                       |
| 400      | `IDEMPOTENCY_KEY_REQUIRED`              | Send an `Idempotency-Key` on every write.                              |
| 401      | `UNAUTHORIZED`                          | Send `Authorization: Bearer keyId:secret`.                             |
| 403      | `KEY_WRONG_ADDRESS`                     | Use a Test key on the Test address and a Live key on the Live address. |
| 403      | `IP_NOT_ALLOWED`                        | Live only: add your server's IP address to the key.                    |
| 403      | `KYC_NOT_APPROVED`                      | Live only: finish your organisation's KYC.                             |
| 403      | `MODULE_NOT_ENABLED`                    | Ask Kitionz to switch on the Flight API for your organisation.         |
| 429      | `RATE_LIMIT_EXCEEDED`                   | Wait for the `Retry-After` time, then send again.                      |
| 500, 503 | `INTERNAL_ERROR`, `SERVICE_UNAVAILABLE` | Send again later. On Book, send the same request with the same key.    |

Every error has `error.code`, `error.message` and `error.request_id`. Quote the `request_id` when you write to [support@kitionz.com](mailto:support@kitionz.com). Every code: [Error codes](/errors).

## Renamed fields

Answers carry the old names beside the new ones until the next release. These pages use only the new names, and their examples leave out every field the API reference marks deprecated. “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, Available dates                |
| `sourceCode`                | `supplierCode`                                                                                                      | 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`                                                                                                   | Origins and Destinations airports (and `airportName` on Available dates)                                    |

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`.

## Glossary

| Term                                | Meaning                                                                                                                                        |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **offer**                           | One price for one set of flights from one seller, from Search. Its id is `offerId`.                                                            |
| **one-way offer**                   | An offer with `tripType: "ONE_WAY"` and one leg.                                                                                               |
| **round trip**                      | An offer with `tripType: "ROUND_TRIP"`: two legs, one price for both ways, a fixed `returnDate`.                                               |
| **leg**                             | One direction of an offer (`OUTBOUND` or `RETURN`). A leg has one or more flights.                                                             |
| **flight (`segments[]`)**           | One take-off and landing under one flight number.                                                                                              |
| **quote**                           | The live price of one offer from Fare quote, with its `quoteToken`.                                                                            |
| **booking**                         | What Book records. Its id is `id` (`bkg_…`).                                                                                                   |
| **PNR (`pnr`)**                     | The airline's booking code. The traveller uses it to check in.                                                                                 |
| **supplier**                        | The system Kitionz searches and books through, for example a marketplace. Switched on per organisation; listed by Your suppliers.              |
| **seller (`seller`)**               | The company that sold the seats: on a marketplace, the agency behind the supplier. Named on every booking.                                     |
| **request booking**                 | An offer with `booking.requestBooking: true`. Book records a request; you book on the seller's site and send the PNR with Submit PNR.          |
| **hold**                            | Seats kept without a ticket (`HELD`). Ticket them before `nextAction.deadlineAt`.                                                              |
| **fare kind (`inventoryCategory`)** | `SERIES`: seats bought in advance and resold. `ONLINE`: live airline fares.                                                                    |
| **party**                           | The passengers: `adults`, `children`, `infants`. Fare quote and Book are for the party you searched with.                                      |
| **Test / Live**                     | Test: `sandbox-api.kitionz.com`, `atz_test_` keys, Kitionz Test Air, nothing booked. Live: `api.kitionz.com`, `atz_live_` keys, real bookings. |
| **Kitionz Test Air**                | The Test supplier. Each `fareFamily.code` rehearses one outcome.                                                                               |
| **Not stated**                      | A value the seller did not give: `null`, or `NOT_GIVEN` for a policy. Never shown as 0, "Economy" or "No baggage".                             |
| **next action (`nextAction`)**      | What you do next with a booking: `WAIT`, `ISSUE_TICKET`, `SUBMIT_PNR`, `SEARCH_AGAIN`, `CONTACT_SUPPLIER` or `NONE`.                           |
| **journey key (`journeyKey`)**      | The same value on offers that state the same flights at the same times. Use it to group copies; book one offer by its `offerId`.               |