4 · Search
Search flights.
What: find bookable offers for a route, date(s) and passenger mix across every supplier you have enabled.
When: the start of every booking — or on its own to display fares.
Before / After: optionally call /origins + /destinations to build the form → here → pick one offer and send its offerId → /fare-quote.
Gotchas
- Read the new names — the old ones are removed in the next release. Each new name has the same value as its old one until then, and the reference marks the old name deprecated.
price(totalAmount,currency,baseFare,taxes,commission,tds,netPayable,publishedTotal,passengerFares[{ passengerType, count, perPerson, total, baseFare, taxes }],infantFare— eachnullwhen the seller did not state it) forpricing;legs[]andsegments[]origin/destination({ iataCode, name, city, countryCode, timezone }) fororiginCode/originName/departureTimezoneanddestCode/destName/arrivalTimezone;segments[].departureTerminal/arrivalTerminal/cabinfororiginTerminal/destinationTerminal/cabinClass;marketingCarrier.iataCodeformarketingCarrier.code; a technical stop’sairportforairportCode/airportName;policy.refund/policy.changeforpolicy.refundPolicy/changePolicy;isInternationalforrequiredPassengerFields.international;booking.requestBooking(besidebooking.bookable) forbooking.viaSupplierApi: false;supplierCodeforsourceCode;sellerforsupplier.priceholds every part ofpricing:netPayable,publishedBaseFare/publishedTaxes,taxBreakdown[](taxComponents),commercials[](withpassengerType,owner) and each row’sbaseFare/taxes. Carriers are one shape{ iataCode, name, flightNumber }(null, never"", when not stated); airport objects take every fact from the Kitionz airport list (null when the airport is not in it). The offer-levelcabin, a leg’scabinClassandfareFamily.cabinare removed in the next release: read each flight’scabin. tripTypeis optional. Leave it out and you get every trip kind leaving ondepartureDate: one-way fares AND round-trip offers.ROUND_TRIPgives round trips only.ONE_WAYcan also return round trips. Some suppliers answer a one-way search with round-trip packages too. Kitionz returns them: each saystripType: "ROUND_TRIP"and has itsreturnDate. ReadtripTypeon every offer and show it as what it is; never assume an offer is the kind you searched. To get every package, sendROUND_TRIPor leavetripTypeout: a supplier that keeps one route list per trip kind is asked in a one-way search only where its one-way list has the route and date.returnDateis the day your traveller flies back. With it, every round-trip offer has thatreturnDate: the local date its return leg leaves. Round-trip offers that return on other days are not inoffers:meta.otherReturnDatescounts them per day. Search again with thatreturnDateto see them.otherReturnDatescounts only the round trips suppliers already sent; it is not a calendar of every return day. Without areturnDate, you get the round trips leaving ondepartureDate, each with its ownreturnDate.- A
returnDatewith notripTypeis a return journey: one-way offers and the round trips back onreturnDate. Read each one-way offer’s route (legs[0].origin.iataCode→destination.iataCode); never assume it flies your way out. Today they all do; one-way offers flying back will come in this same answer later. AreturnDateis refused (400) withtripType: "ONE_WAY", and withslices(the date of your second slice is your return date). - Each offer says which trip it is:
tripType(ONE_WAY|ROUND_TRIP),departureDate, and — for a round trip —returnDate, fixed by the fare. A round trip’s price covers both ways: label it so in your screen. SenddepartureDateback unchanged on/fare-quoteand/book. Book each offer by its own labels: send the offer’stripTypeandreturnDate, never the search’s. They may be left out there (the offer’s own are used); when sent they must be the offer’s (a different trip →400 OFFER_TRIP_MISMATCH). - A round trip is ONE offer with
legs: [OUTBOUND, RETURN], onetotalAmount, oneofferId: one fare for both ways, booked with one/fare-quoteand one/book. It can be a series package (seats bought in advance and sold as a pair) or a return fare. Never staple two one-ways together. - Today round trips come only from suppliers whose catalogue offers them. With
tripType: "ROUND_TRIP", every other supplier is listed inmeta.suppliersExcludedwith reasonROUND_TRIP_NOT_OFFERED(left out, not a failure). - Some suppliers need your return date to find round trips. With a
returnDate, Kitionz asks them for that day only, never for other days, so their other return days are not inotherReturnDates. When Kitionz already holds such a supplier’s list of return days and your day is not on it, the supplier is not asked and is listed inmeta.suppliersExcludedwith reasonRETURN_DATE_NOT_LISTED(left out, not a failure). - A supplier whose fares are all of a category your
filters.inventoryCategories(or your connection) leaves out — e.g. a series-only supplier when you ask forONLINE— is not asked at all: it is listed inmeta.suppliersExcludedwith reasonINVENTORY_NOT_REQUESTED(left out, not a failure). - A supplier that publishes a date list is asked on every date its list shows. When its current list leaves the date out, it is not asked and is listed in
meta.suppliersExcludedwith reasonDATE_NOT_LISTED(left out, not a failure). A supplier with no date list is asked on every one-way search (a round trip goes only to suppliers whose catalogue offers round trips, see above). - Some suppliers return their round-trip packages together with their one-way fares, from one date list for both. Their listed dates count for both trip kinds: a
tripType: "ROUND_TRIP"search asks them on any listed date, and a search with notripTypeasks them once and returns both kinds. - With
slicesthe slices decide the kind (one slice = one-way, two = round trip); sendtripTypeonly if it agrees. The first slice must be the same trip asorigin,destinationanddepartureDate, and a second slice must be its exact way back. Never sendreturnDatewithslices: the date of your second slice is your return date, andmeta.otherReturnDatesis filled for it too. Refused (400): three or more slices, and a second slice to other airports (open jaw) — multi-city search is not available. - Filters work for every supplier. Kitionz applies
cabinand everyfiltersfield to the offers suppliers return:cabinreads the offer’s owncabinwhen it states one, otherwise each flight’scabinClass(a cabin not stated keeps the offer);refundableOnlykeeps onlyREFUNDABLE(NOT_GIVEN— not stated — is left out);maxConnectionscounts changes of flight per direction (0= no change of flight; a technical stop on the same flight is allowed; a stop with no airport stated counts);airlines.include/excluderead each flight’s marketing carrier;fareBrandsInclude/ExcludereadfareFamily.code;maxOffersPerSupplierkeeps each supplier’s cheapest. An empty list is no filter; a filter name Kitionz does not know is refused (400).meta.suppliers[].offerCountcounts the offers left after your filters. meta.filtersAppliedsays what each filter removed: one entry per filter you sent,{ field, removed }— an offer two filters remove counts under both. Read it when an answer is empty: few suppliers state a fare brand or a refund policy, sofareBrandsIncludeorrefundableOnlycan remove every offer, and the entry says so.maxOffersPerSupplierwith notripType: one-way fares and round-trip packages share one price list per supplier, so a small number can leave out every package (packages usually cost more). SendtripTypeto cap one kind only.- An airport code Kitionz does not know (not an IATA airport or city code it has) is not refused today: suppliers are still asked, and the envelope
meta.diagnosticscarriesUNKNOWN_AIRPORTnaming the field and the code. Check the code. A real airport nobody sells from returns 200 with no offers and no such diagnostic. The same holds on/destinationsand/availability. meta.tripTypeslists the kinds this search covered; eachmeta.suppliers,meta.suppliersFailedandmeta.suppliersExcludedentry carries thetripTypeof its part (one supplier can appear once per kind) — so the same supplier can be insuppliersSucceeded(one kind answered) and insuppliersFailed(the other failed).supplierCounts, when present, counts distinct suppliers in each list. ADEADLINE_EXCEEDEDentry withtookMs: 0means the search ran out of time before that part asked the supplier.- Search prices are indicative — never charge off them; re-price at
/fare-quote. - Pax fields are
adults/children/infants(same names across the whole flow). - Search with the passengers you will book. An offer is quoted and booked only for the adults, children and infants it was searched for; another party gets
400 PASSENGER_COUNTS_CHANGEDat/fare-quoteand/book(for every supplier). Each offer’sexpiresAtsays when Kitionz stops accepting itsofferId(not a price guarantee). - With infants, read
price.infantFare.status.PRICED: the supplier’s infant price is theINFANTrow ofprice.passengerFaresand insideprice.totalAmount.NOT_GIVEN: the supplier gave no infant price, so that row’stotalisnullandprice.totalAmountcovers adults and children only. Add your own infant charge (the supplier or airline may still charge for the infant), or hide such fares — your choice. Kitionz never hides a fare and never shows ₹0 for a missing infant price. Treat any other status asNOT_GIVEN, and add your infant charge before you sort by price. - Count each passenger by age on the last flight of the trip (the return flight on a round trip):
ADULT12 or older,CHILD2–11,INFANTunder 2. A baby who turns 2 before the return is aCHILDfor a round trip but anINFANTfor a one-way fare — when one search returns both, the party you sent fits only one of them;/bookrefuses the other. supplierCodesis optional — leave it out. Kitionz already knows which suppliers your key is enabled for and searches all of them. SendsupplierCodesonly to narrow to a subset of THOSE (blanks ignored; a non-enabled code → 403). Don’t send the empty[""]from the example skeleton. (sourcesis its old name, accepted until the next release.)- Each offer carries
capabilities{ seatSelection, meals, extraBaggage, hold, fareRules, cancellation: REALTIME|OFFLINE|NONE }— a supplier-level hint; the exact per-offer answer comes at/fare-quote(eligibility), and/bookrejects an unsupported action with a typed 422 (e.g.HOLD_NOT_SUPPORTED_FOR_THIS_OFFER). Useholdandcancellation. Do not build seat, meal or extra-baggage selling on this: no Live supplier offers them today (only Kitionz Test Air shows a seat map), and/booktakes no seats, meals or bags. - How an offer books: read
booking.bookableFIRST.bookable: false→ show the fare, don’t offer to book it (requestBookingis thenfalse).bookable: true+requestBooking: false→/bookbooks with the supplier; the booking’sstatustells you whether the PNR came back on that call or follows.bookable: true+requestBooking: true→/bookrecords a request (PENDING_FULFILMENT); book on the supplier’s portal, then/bookings/:id/fulfil. In code:if (!booking.bookable) … else if (booking.requestBooking) … else …. (booking.viaSupplierApiis the old name:falsewhererequestBookingistrue, absent when not bookable.) - The same flights often come back from several sellers — Kitionz returns every offer and never removes a copy. Group them by
journeyKey: equal keys mean the sellers state the same flights at the same start and end times (same airline and flight number, same airports including stops, each leg leaving and arriving at the same local time). Price, seats, baggage and rules differ per offer: never add seats across a group, and book one specific offer with its ownofferId. Each leg has alegKey(same rule, one direction) — equal leg keys never let you split a package or join two one-ways. WhenjourneyKeyComparableisfalse(reasons inlegs[].legKeyGaps) the key is unique to that offer: show it on its own. The key changes when an airline retimes a flight or Kitionz learns a fact a seller left out. The recipe (versionjk1) is published so you can key your own inventory the same way.
Example — request (only origin / destination / departureDate / adults are required):
Response (trimmed) — send an offer’s offerId to /fare-quote. Read the new names shown; until the next release each flight also carries its old names (here marketingCarrier.code, originCode, destCode):
Example — a return journey (one-way offers and round trips back on 19 Jan):
Response (trimmed) — one round-trip offer comes back on 19 Jan; two others come back on 20 Jan and are only counted:
Authentication
Your Kitionz API key, sent as Authorization: Bearer keyId:secret. Create a Test key at sandbox.kitionz.com → API keys, a Live key at kitionz.com → API → API keys.
Request
The day your traveller flies back. Every round-trip offer in the answer has this returnDate (the local date its return leg leaves). Round-trip offers that return on other days are counted in meta.otherReturnDates. With tripType left out you get one-way offers and round trips back on this day: read each one-way offer’s route, never assume it flies out. Not allowed with tripType ONE_WAY, nor with slices (the date of your second slice is your return date).
Optional. Left out: every trip kind — one-way fares and round trips. ROUND_TRIP: round trips only. ONE_WAY: one-way fares, plus any round-trip packages a supplier’s one-way answer carries; each says tripType ROUND_TRIP with its returnDate. Read tripType on every offer and book it by its own labels: send fare-quote and book the offer’s tripType, never the search’s. To get every package, send ROUND_TRIP or leave tripType out.
Optional. The cabin to fly. Kitionz passes it to the suppliers that take a cabin, and leaves out an offer whose cabin is another one: the offer’s own cabin when it states one, otherwise each flight’s cabinClass. A cabin that is not stated (absent or null) keeps the offer. Left out: every cabin.
Optional. Leave it out to use every supplier your account has switched on. Send a list of supplier codes (each supplier’s code in GET /v1/flights/suppliers) only to narrow this call to some of them; a code you cannot use is refused (403), and blank entries are ignored.
Optional. One slice (a one-way) or two (the way out, then its exact way back). The first slice must be the same trip as origin, destination and departureDate; the second must fly from its destination back to its origin. Three or more slices, or a second slice to other airports (open jaw), are refused (400). Most searches leave slices out and send returnDate instead.
Optional. Kitionz applies every filter to the offers suppliers return, the same way for every supplier. A filter only removes offers; meta.filtersApplied says how many each one removed. An unknown filter name is refused (400).
Response
Flight-search result envelope: searchId + offers + per-supplier meta (partial supplier failures are surfaced in meta.suppliersFailed, never as a top-level error).