info.version in the OpenAPI document, and each section below is one version of it. The rules for what counts as breaking and how much notice a removal gets are on Versioning & deprecation.
This page starts at 0.57.0 (2026-10-13). Earlier versions are not listed one by one; Contract changes on Versioning & deprecation describes what changed in 0.26.0, 0.33.0 and 0.39.0.
0.86.0
Not yet released. Changed Corrections to thePOST /v1/flight_search document only; nothing on the wire moves (the second step of the live flight search review, JIN-2837).
via_airportsrestricts every connection of a leg to the listed airports, not “at least one”. Some providers are asked for at most the first 9 per leg; the whole list is applied to what they return, and the 200 description no longer claims a 9-airport cap.- The filters
refundable_only,changeable_onlyandchecked_bag_includedare no longer described as the same predicate as the fare flagsis_refundable,is_changeableandchecked_bag_included. The filters read the before-departure rules only, and the bag filter needs a free bag on every segment; the flags are folded from every rule (an after-departure rule alone makes themtrue) and the bag flag reads the first segment that states an allowance. max_total: conversion tocurrencybefore the comparison is the usual case, not the rule. A provider whose first priced offer is already incurrencydrops its other-currency offers as unverifiable.offers[].offer_idisoffer__followed by 8 hex characters (the example wasoff_…). It is theoffer_tokenof a re-price and the prefix of eachtrip_item_token, which is now described with a real-shaped example.offers[].origin.codeanddestination.codeare the city codes of the requested pair, never the airport flown, and can be an empty string when the platform cannot map the code to a city. The examples are city codes and names.- On a live segment,
flight_numberis a bare number (the cached segment keeps the either-form text),departure_cityandarrival_cityare IATA city codes (the examples were names), andoperating_carrieris no longer promised on every segment: whether equality withairlineis stated depends on the provider. offers[].fares[].expires_at: the platform’s token lifetime is 75 minutes fromsearched_at, not 30.included_baggageandcarry_on_baggageare read from the first segment that states an allowance, not per leg. Theirdescriptionis text the platform writes from the allowance (1 bag, 23KG each,No checked bags included,1 carry-on bag), not the carrier’s prose;weight_unitisKGorLB, absent when no recognised unit was stated.refund_policyandchange_policylist all eight values each: the four base terms and theirafter departurevariants. A cancellation rule with an unspecified penalty readsNon-refundable; a change rule with one sets no policy.- Fields that had no description now have one:
departure_date;offer_token(a cached-itinerary token is re-shopped live andexact_match_foundsays whether the same flights and cabin were found; anoffer_idfrom an earlierflight_searchis answered from the cache of that search unless the passengers orcurrencydiffer, and answers410 OFFER_EXPIREDonce its fares have expired);multi_fare(at most 10 fares per offer);connection_time_min_minutes,connection_time_max_minutesandaircraft_types(an itinerary the filter cannot verify is dropped);same_origin_airport_onlyandsame_turnaround_airport_only(round trip only, no effect on a one-way search);limit(omitted means the cheapest flight plus up to 100 alternatives); the segment’saircraft(absent when the provider reports no equipment); and the fare’sbrand_name.
0.81.0
Not yet released. Removedaircrafton the segments of a cached itinerary, onPOST /v1/flight_calendar,/v1/find_dates,/v1/lowest_fareand/v1/find_destination. The cache carries no equipment, so the field was never sent there; it leaves the document and no response changes. The cached itinerary’s legs are now their own components,CachedFlightLegandCachedSegment, with the same fields and types asFlightLegandSegment, whichflight_searchand the booking reads keep unchanged,aircraftincluded.
- On a cached leg or segment, a datetime at an airport whose timezone the platform does not know is written as UTC (
…Z) with its local wall-clock digits. The shared text said the offset was omitted, which is what a live leg does. The live text now scopes its*_localremark to booked and exchanged itineraries. operating_carrieron a cached segment is sent only when the cached record carries one. The shared text promised it was always sent, equality withairlineincluded.limitis described per route: onflight_calendara global cap on the sorted itineraries; onfind_datesthe number of date pairs, each with its cheapest itinerary, default 20, where the route summary promised ten; onlowest_farenot applied, the route returns at most ten itineraries; onfind_destinationthe number of destinations.- On
POST /v1/price_monitoring,statusis the enumok|stalerather than a free string; the four*_localdatetimes carry the airport’s UTC offset (RFC 3339) despite their suffix, as they always did on the wire, and their examples now show it;inbound_stopsis documented as omitted on a one-way monitor and on a non-stop return, unlikeoutbound_stops, which is always sent.
0.80.0
Not yet released. Deprecatedamountonprice_per_personof aPOST /v1/flight_searchfare leaves the OpenAPI document. The per-person fare is now published asMoneyWithoutAmount: theMoneyshape without its deprecatedamountmember —value(an integer in minor units),currency,decimal_placesanddisplay, unchanged. The platform never setamounton this figure, so no response changes; the member stays in the code for now and is listed under Deprecated fields.total_priceon the same fare is unchanged.
0.79.0
Not yet released. Deprecated- The passenger fields on the cache-backed flight requests leave the OpenAPI document:
adults,children,infants_in_lap,infants_in_seat,youth,student,agesandresidency_countryonPOST /v1/flight_calendar,/v1/find_dates,/v1/lowest_fareand/v1/find_destination, andadults,childrenandinfantsonPOST /v1/price_monitoring. Every cached fare is one adult’s whatever party is sent (priced_for: one_adult), so none of them ever changed an answer. A request that still sends one is accepted, validated and answered exactly as before, withDeprecation: trueand the deprecated-inputsLink; no removal date is set yet. They are listed under Deprecated inputs. Price a party withPOST /v1/flight_search, which is unchanged. - On those requests a
passengersobject is still refused with 422, and the message now says the request takes no passenger counts instead of naming the fields above.
0.78.0
Released 2026-10-19. Added- Seat maps:
GET /v1/trip/{trip_id}returnsseat_map_url, a link to a page where the traveler picks seats on a seat map. The link expires; read the trip again for a fresh one. See Seats. - Seat offers in
GET /v1/trip/{trip_id}/ancillariescarryseat_map_status:pendingwhile the seats are still loading,readyonce they can be selected. - Selected and booked seats can carry
not_charged: true: this seat is not charged to the traveler.
0.77.0
Released 2026-10-19. Restored Inputs and a response field removed without notice since 2026-08-29 that the platform still serves come back, deprecated, until 2027-04-30. A request that uses one of the restored inputs is answered as it was before the input was removed, withDeprecation: true, the deprecated-inputs Link and Sunset: Fri, 30 Apr 2027 23:59:59 GMT; each is listed under Deprecated inputs. The restored response field sends no header, since reading a field is invisible to the server: it is marked deprecated in the OpenAPI document and listed under Deprecated fields.
- The two
enable_*query parameters onhotel_searchthat turned individual hotel suppliers on or off, refused since 0.57.0, are accepted and ignored: the platform chooses which hotel inventory to search. date_flexibility_daysonPOST /v1/flight_search, refused since 2026-08-31, is accepted within its published range (an integer from 0 to 3) and ignored: the search runs on the exact dates, as it did then.- On
POST /v1/exchange_shop, asegments_to_exchangeentry may again name its airports as flatorigin/destinationcodes, read as airports, and an emptysegments_to_exchangereshops like leaving the field out, as before 0.43.0. hotel_refis back onhotel_searchhotels and nearby alternatives,hotel_details.hotelandhotel_reviews.hotel, markeddeprecatedand sent until 2027-04-30 (listed under Deprecated fields).hotel_id(search) andid(details, reviews) stay the identifier to use.
ticket_numberson the refund and exchange routes,place_idonhotel_searchand a child age outside 0 to 17 stay refused.
0.76.1
Released 2026-10-18. ChangedPOST /v1/bookanswers until 2027-04-30 instead of 2026-12-31; itsSunsetheader says so. The earlier date, published on 2026-09-07, gave less than the 180 days of notice this policy promises./v1/bookstays deprecated in favour ofPOST /v1/checkout.
0.76.0
Released 2026-10-18. Added- A request that uses a deprecated input is answered with
Deprecation: trueandLink: <https://docs.gojinko.com/concepts/versioning#deprecated-inputs>; rel="deprecation", and withSunsetwhen the input has a removal date. The response is otherwise unchanged; a request refused for naming one value under both its old and new name carries the headers too. The deprecated inputs are listed on Versioning & deprecation. refund_check,refund_commit,refund_statusand the one-stephotel_cancel, deprecated in 0.74.0, answer withDeprecation: trueand aLinkto the route that replaces each (rel="successor-version"). No removal date is set, so they send noSunset.
- The booking handles 0.57.0 removed without notice are accepted again, deprecated, until 2027-04-30:
order_idinstead ofbooking_refonrefund_check,refund_commit,refund_statusand the exchange routes;provider_referenceinstead ofbooking_refandlast_nameonflight_refund_preview,flight_refund_commit,flight_refund_status,hotel_cancel_preview,hotel_cancel_commitandhotel_cancel_status;provider_booking_idthe same way onhotel_cancel; andprovideron the flight refund and exchange routes and onhotel_cancel, which the platform does not need. A handle sent besidebooking_refis refused with 422.booking_refis optional on these routes again, and required when no handle names the booking. A request that sends a handle getsSunset: Fri, 30 Apr 2027 23:59:59 GMT.
0.75.0
Released 2026-10-18. Addedbooking.completeddata listsitems[]: each booked item with itsitem_id,kind,booked_item_idandsupplier_references, asbooking.partiallists its completed items. You no longer need aget_bookingcall after every booking to learn the airline or hotel reference.booked_item_idis theitm_handleget_bookingnames the item by, and is omitted when the platform cannot name it. Events sent before this version carry noitems.
0.74.2
Released 2026-10-18. Fixedexchange_priceandexchange_commitrefuse an emptyoffer_idwith 422BAD_REQUEST. It used to come back as 502UPSTREAM_ERROR.get_bookingbooked_ancillaries[].typelists every kind that is booked:seat,bag,meal,cabin_bag_upgrade,sports_equipment,priority_boarding,assistance,insurance,lounge,frequent_flyer,other. The contract said seats only while bags and meals were already listed.flight_refund_previewandhotel_cancel_previewdocument the 409active_operation_existsa preview answers while another operation is in progress on the item, naming it inactive_operation.- Payment attempt answers document that
trip_idcarries thetrip_prefix, which the trip answers do not.
0.74.1
Released 2026-10-18. Fixedget_booking:booking.booking_refanditems[].booking_refare always the booking’s own Jinko reference, including after an exchange and when the booking is looked up with the reference of one of its exchanges. In 0.74.0 an exchanged item named the exchange’s own reference. The deprecatedbooking_referencefields keep their meaning.
0.74.0
Released 2026-10-17. Breakingerror.codeis uppercase everywhere.attempt_in_progress,attempt_terminal,credential_format_invalid,departure_date_in_past,idempotency_key_reused,invalid_exchange_request,invalid_segments_to_exchange,leg_already_departed,leg_dates_out_of_order,not_exchangeable,partial_exchange_unsupported,payment_credential_invalid,payment_type_not_enabled,temporarily_unavailableandtrip_owned_by_other_paymentare now sent in uppercase (for exampleATTEMPT_IN_PROGRESS), andquote_expiredis nowQUOTE_EXPIRED.payment_error.codeon payment attempts and payment refusals is uppercase, with the same codes aserror.code.- On refund and cancellation conflicts, the sibling
codequote_expired→QUOTE_EXPIRED. The other sibling codes are unchanged. - Exchange and ancillary
statusvalues are lowercase:confirmed,pending,partial_failureandfailedon theexchange_commitandexchange_statusanswers;pending,confirmedandfailedon selected and booked ancillaries. failure_reasonreadsoffer_unavailable, where it readoffer_not_available, in thebooking.faileddata and wherever a booking failure is reported.- The travel demand
trip_typeisonewayorroundtripon/v1/destination,/v1/market,/v1/audience,/v1/trend,/v1/destination/trend,/v1/market/trendand/v1/audience/trend. Requests still acceptOne-WayandRound-Trip.
booking_stateonGET /v1/trip/{trip_id}and on the bookingget_bookingreturns: a summary of the booking’s progress after payment, one ofawaiting_payment,processing,completed,partial,failed,cancelledorneeds_review. It is absent before payment.fulfillment.status, the booking’sstatusandbooking_statusstay as the detailed status.POST /v1/agent_payment/submitdeclares 404NOT_FOUNDwhen the trip, or thequote_idamong its quotes, is not found. Nothing is charged.- The answer to the legacy flat body of
POST /v1/agent_payment/submitnames the quote it charged asquote_id.
- Renamed request fields. Only the new name is documented; the old name is still accepted. Sending both names with different values is refused with 422
BAD_REQUEST, or 400CREDENTIAL_FORMAT_INVALIDon a typed payment body.- The integer
item_id→booked_item_idonrefund_check,refund_commit,refund_status,flight_refund_preview,flight_refund_commit,flight_refund_status,hotel_cancel,hotel_cancel_preview,hotel_cancel_commit,hotel_cancel_status,car_cancel_preview,car_cancel_commit,car_cancel_status,exchange_shop,exchange_price,exchange_commitandexchange_status. quote→quote_idonflight_refund_commitandhotel_cancel_commit;cancellation_id→quote_idoncar_cancel_commit;session_reference→quote_idonexchange_commit; the deprecatedquoted_cart_id→quote_idon the typedPOST /v1/agent_payment/submitbody.max_price→max_totalonflight_searchandprice_monitoring.offer_id→trip_item_tokenon the Best Price Guarantee claim.pax_ref_id→traveler_refonselect_ancillariesselections;passenger_type→traveler_typeonupsert_travelers.
- The integer
- The webhook
event_idis documented as an opaque string, unique to each occurrence. Its format is not part of the contract. - On the cached flight searches,
max_totalis documented as a cap on the cached fare’s total, and cached fares are priced for one adult.direct_onlyis documented as their only stop filter.
- Renamed response fields. Each new field is sent beside the old one, which keeps the same value and is marked
deprecated: true. No removal date is set.quoted_cart_id→quote_idon the checkout answer, the trip’squote, the trip ancillaries answer, payment attempts, payment refusals and the quote-expired answer;quote→quote_idon the flight refund and hotel cancellation previews;cancellation_id→quote_idon the rental car cancellation answers;session_reference→quote_idonexchange_price.quote_idis a string, and the deprecated names stay beside it.requote→retry_quote_idon refund and cancellation conflicts.booking_reference→booking_ref, the Jinko booking reference, on theget_bookingbooking and its items, theexchange_commitandexchange_statusanswers and the one-stephotel_cancelanswer;fulfillment_cart_id→booking_refon the trip’sfulfillment, payment attempts and the legacy agent payment answer. The deprecatedfulfillment_cart_idis an internal number.- The integer
item_id→booked_item_id, theitm_handle the servicing routes take, onget_bookingitems and on payment attemptitems[]; the integeritem→booked_item_idon servicing webhook data;item→booked_item_idon the refund and cancellation previews, whereitemalready held the sameitm_value. quoted_item_id→item_idon theselect_ancillariesanswer.pnrandairline_locatorson flight details,hotel_confirmation_numberon hotel details,confirmation.confirmation_number,bookings[].booking_reference,bookings[].pnrand thebooking.partialitem’sbooking_reference→supplier_references[], one{ issuer, reference }per confirmation the airline, hotel or rental company itself issued,[]when none is known. It is on eachget_bookingitem, eachbookings[]entry ofGET /v1/trip/{trip_id}and eachbooking.partialitem.- The single
airline_locatoron the exchange answers andconfirmation_numberon the one-stephotel_cancelanswer: read the booking’ssupplier_references[]fromget_bookinginstead. offer_id→trip_item_tokenon hotel, rental car and Best Price Guarantee offers. Theoffer_idecho on trip items and bookings is deprecated; hotel and rental car items now also echotrip_item_token.id→offer_tokenon cached itineraries.pax_ref_id→traveler_refandpassenger_type→traveler_typeon stored travelers and on ancillaries.traveler_typeis lowercase:adult,child,infant.reason_code→failure_reasonin the booking failure email content, in the words of thebooking.faileddata.stripe_checkout_session_url→checkout_urlonexchange_commit.
stripe_referenceandstripe_refund_id.refund_check,refund_commitandrefund_status, in favour offlight_refund_preview,flight_refund_commitandflight_refund_status; the one-stephotel_cancel, in favour ofhotel_cancel_preview,hotel_cancel_commitandhotel_cancel_status.- The webhook envelope’s
status: branch onevent, which already names the outcome. - The trip
statusvalues that describe booking progress (fulfilling,fulfilled,partially_fulfilled,failed): readbooking_state.
POST /v1/checkoutsays it waits about 55 seconds for the quote. It said 25.GET /v1/trip/{trip_id}/ancillariesdeclares its 202 answer (status: "pricing", withRetry-After), which it already returned.Idempotency-Keyis documented as required on a typed payment submission. A submission without it is refused with 400CREDENTIAL_FORMAT_INVALID.originis documented as required on/v1/destinationand/v1/destination/trend, which refuse a request without it.TRIP_STATE_CONFLICTno longer says a trip refuses writes while it is being quoted. A trip refuses writes once payment has started, or when it is cancelled or failed.QUOTE_PENDINGlistsquote_idamong its extra keys.
0.73.0
Released 2026-10-17. Deprecated- On
hotel_search, each of these is still accepted or still sent with its behaviour unchanged. No removal date is set.adults,childrenandrooms→occupancies, one element per room, with children given bychildren_ages. The shorthand is ignored wheneveroccupanciesis sent.star_rating→min_star_ratingandmax_star_rating.star_ratingonly fills a bound the request leaves unset.offset→next_handle. A search that answers withnext_handlealready refuses a non-zerooffset.- The
search_handleanswer field →next_handle. No endpoint acceptssearch_handle.
0.72.0
Released 2026-10-17. Breakinghotel_refis removed fromhotel_searchhotels, fromhotelonhotel_detailsand fromhotelonhotel_reviews. One identifier remains:hotel_idon a search hotel andidon details and reviews, with the same value./v1/hotel_details/{hotel_id}and/v1/hotel_reviews/{hotel_id}take that value, and still accept ahotel_refkept from an earlier search.
hotel_idis opaque. Pass it back exactly as received tohotel_details,hotel_reviewsandhotel_ids. Do not parse or build it, and do not keep it across contract versions: the value a hotel is known by can change, so read it from a freshhotel_search.
- The
hotel_detailsexampleidshows the same value as thehotel_searchexample.
0.71.0
Released 2026-10-17. Addedhotel_searchdeclaresdestination_resolution.radius_source, which destination searches already sent besideradius_km:callerwhen the request’s ownradius_kmwas searched,citywhen the radius came from the spread of the resolved city’s hotels (no smaller than the platform minimum), anddefaultwhen coordinates came without a radius and the platform default was used. Acityordefaultradius may be widened when the first search finds too little;radius_kmis then the radius finally searched. It is absent on thehotel_nameandhotel_idsshapes.
destination_resolution.place_id, andplace_idas a value ofdestination_resolution.shape. No answer carried them, since aplace_iddestination is refused on input with 422.shapeis one ofcity,coordinates,query,hotel_nameandhotel_ids, and its description says which other fields each one brings.
0.70.0
Released 2026-10-17. Breakinghotel_searchno longer returnspagination, which some destination searches sent although the contract never declared it. Page withnext_handle,has_moreandexpires_at;totalstill counts the hotels on the page.- Each entry of
hotels[].offers[]andnearby_alternatives[].offers[]no longer carriessemantic_matches,promotions[].codeorroom_rates[].rate_id. No operation acceptedrate_id.promotions[].nameandpromotions[].remark, which must be shown to the guest, stay, as doroom_id,occupancy_number,occupancyand the rest of each room rate. The deprecatedrooms[].rates[]shape, including its promotioncode, is unchanged.
0.69.0
Released 2026-10-17. Breakinghotel_searchno longer returnsbudget_filter, the report of howmax_budget_per_nightwas applied. The filter itself is unchanged:max_budget_per_nightstays on the request, every hotel returned fits it,empty_reasonisall_dropped_by_budgetwhen none did, andwarningsstill carries the budget advisories.hotel_searchno longer returnssearch_context.trip_id.trip_idon a first request is no longer declared; a request that still sends it is accepted and the field is ignored. It never selected, priced or filtered anything. Adding a hotel offer to a trip withPOST /v1/tripis unchanged.
0.68.0
Released 2026-10-17. Breakinghotel_searchno longer returnssearch_scope, which described how the search ran:plan_kind,coverage,snapshot_size,candidate_count,coverage_unknown,truncated,widened_from_kmandproviders[]. Paging is unchanged, anddestination_resolutionstill reports the radius a destination search ended at.
0.67.0
Released 2026-10-16. Breakinghotel_searchno longer returnsintent_match_probability,intent_confidence,intent_evidence_statusorintent_factson hotels inhotelsandnearby_alternatives, norinternal_searchon the answer.distance_kmandrecommendation_scorestay, and the order ofhotelsandrecommendation_scorestill reflectintent.user_intent.
0.66.0
Released 2026-10-16. Fixed- The legacy flat body of
POST /v1/agent_payment/submitno longer declaresintent. A body that still carries it is accepted and the field is ignored. Before, such a submission was refused withCREDENTIAL_FORMAT_INVALID.
0.65.0
Released 2026-10-16. Breaking- The Best Price Guarantee answer no longer carries
negotiator. Readstatus,offeranddecline;offer.reference.verifiedstill says whether Jinko confirmed the reference.
0.64.1
Released 2026-10-15. Fixed- The Best Price Guarantee answer’s example is one complete
offeredanswer. It showed every money field with the same value, besidedeclineandpoll_after_seconds, which anofferedanswer does not carry. No field or rule changed.
0.64.0
Released 2026-10-15. Addedexchange_shopsays why an exchange is not automatic. Whensupport_levelis notAUTO, the answer carriesreason_code(NOT_EXCHANGEABLEwithUNSUPPORTED,MANUAL_REQUIREDwithMANUAL_REQUIRED) andreason, a fixed sentence to show the customer: “This booking cannot be exchanged online. Contact Jinko support.” or “This request needs manual handling by Jinko support.” AnAUTOanswer carries neither.exchange_priceaddscustomer_amounts.residual_value, in the money shape and in the booking’s charge currency: the part of the original fare the airline keeps as a credit in the traveller’s name after an exchange to a cheaper fare. It is not refunded to the card, is not part oftotal_dueortotal_refund, and is present only when the airline reports one.
exchange_pricecustomer_amounts.new_fareno longer includes the residual value, so the figures add up asoriginal_fare + total_due - total_refund = new_fare + penalty_amount + residual_value. Before, anEVENexchange to a cheaper fare showed a new ticket worth exactly the old one.refund_checkstates a reason on every answer that is notAUTO.manual_reasonis present withUNSUPPORTEDas well as withMANUAL_REQUIRED, and anUNSUPPORTEDanswer always carries areason_code: a refusal that came with no code now carriesNOT_CANCELLABLE. A refusal’smanual_reasonreads the same sentence as theflight_refund_preview409not_cancellablefor that booking, and that 409 carries the samereason_code.provider.references.cancellation_referenceon the refund and cancellation status answers is documented as the reference the supplier issued for the cancellation or refund itself, for example the ticket number a void settles or the refund id. It is never the supplier’s identifier for the booking, and it is absent when the supplier issued none.
0.63.0
Released 2026-10-15. Added- Best Price Guarantee:
POST /v1/best_price_guaranteeandGET /v1/best_price_guarantee/{id}. The submit takes a hotel offer fromhotel_searchand the lower price the traveller found for the same stay on another site. Both routes answer the state of the request:pending,offeredwith a new offer to add to a trip, ordeclinedwithdecline.reasonand, where Jinko compared the reference page,decline.detail. They take ajnk_API key, asX-API-Keyor as a Bearer token. Where the feature is not enabled for your key, the answer is 200 withstatus: declinedanddecline.reason: feature_disabled.
0.62.0
Released 2026-10-15. Addedhotel_searchempty_reasoncan beall_dropped_by_rating_filter: the destination matched properties, but every one fell below the requestedmin_ratingormin_reviews, or below the defaultmin_ratingof 7.0 when the request set none. A property whose rating is unknown is removed only by amin_ratingthe request sets, and one whose review count is unknown only bymin_reviews.
- The
min_ratingdescription states the default of 7.0, and that0turns the floor off on destination searches. - The
hotel_namedescription says property filters sent withhotel_nameorhotel_idsare rejected. It said they were ignored.
0.61.0
Released 2026-10-14. Added- Each flight fare carries
refund_policy(Free cancellation,Refundable,Refundable with feeorNon-refundable) andchange_policybesideis_refundableandis_changeable, stating the refund and change terms in words.
0.60.0
Released 2026-10-14. Breaking- Checkout of a trip with a flight requires a contact email. Without one, checkout is refused with 422
MISSING_CUSTOMER_DETAILSnamingemail. - In a trip with a hotel, a
childorinfanttraveller requires adate_of_birth. A traveller without one is refused on that field. date_of_birthandpassport_expirymust be exactlyYYYY-MM-DD.
- Travellers are checked against the trip before payment. In a trip with a flight,
upsert_travelers(once the trip holds the flight) andcheckoutanswer 400BAD_REQUEST, witherror.fieldnaming the traveller, when adate_of_birthis in the future, whentraveler_typedoes not match the traveller’s age on the date the booking counts ages from (the trip’s first flight, or for some bookings the return flight of a round trip:adult12 or older,child2 to 11,infantunder 2 and still under 2 on the last flight), or whenpassport_expiryis before the trip’s last flight. Before, such a trip reached a payable checkout or failed at checkout with 502UPSTREAM_ERROR. - Each hotel in a trip is booked for the trip’s travellers, or for the room guests that
hotel_room_guestsnames on aroom_bundlehotel. They cannot include more adults or more children than its rooms were priced for, counted by age at check-in, and each child’s age at check-in must be one of the pricedchildren_ages. Otherwise the answer is 400BAD_REQUESTnaming the first traveller over a count or with an age the room was not priced for. - A flight searched for a different party is re-priced at checkout for the trip’s travellers, on the same flights and fare family. When that is not possible, or the airline declines to price the fare, checkout answers 409
OFFER_UNAVAILABLE.
0.59.2
Released 2026-10-14. Changed- A card declined on the payment page is reported on the trip. When the issuer declines the card the payer used on the
checkout_urlpage, or its authentication fails,payment_attempt.payment_error.codeisCARD_DECLINEDorAUTHENTICATION_FAILEDwhilepayment_statusstayspendingandrecovery.actionispoll: the payer can use another card on the same page until the quote expires.payment_errorreturns tonullonce a card is authorized. Before, the trip readpendingwithpayment_error: null.
- On a payment attempt,
booking_refand the deprecatedfulfillment_cart_idare absent until the booking and its reference exist, andretry_after_secondsis present only whilerecovery.actionispoll. None of them is evernull. Before a booking existed, the first two were sent asnull, which the published schema does not allow.
0.59.1
Released 2026-10-14. Addedget_bookingdeclares the booked flight itinerary, which it already sent. Flight details carrylegs[], each with the origin, the destination,departure_datetime,arrival_datetime,stopsandsegments[], and the older namesoutbound_flightandinbound_flightforlegs[0]andlegs[1]. Each segment carries the carriers,flight_number,aircraft, the airports, anddeparture_timeandarrival_time(airport local time with its UTC offset) besidedeparture_time_localandarrival_time_local(no offset). The itinerary is the one booked and ticketed: it is not refreshed from the airline, and no webhook reports an airline schedule change or cancellation. There is no terminal and no per-segment status.- Booking and item
statusvalues are documented as an open set: in progress (frompendingtoconfirming), final (completed,partialon the booking,failed,cancelled,expired_quote) and needing attention (exchange_partial_failure,needs_review). They follow Jinko’s booking and servicing steps, never an airline change.
- The
get_bookingstatus example readscompleted, which a ticketed booking returns. It saidconfirmed.
0.59.0
Released 2026-10-14. Breakingslices→legsonexchange_shopoffers, which no longer carrymetadata. The new fare onexchange_priceno longer carriesbaggage_source. The exchange answers,exchange_commitincluded, carry only the fields the contract declares.exchange_commitno longer returnsexchange_reference. On some exchanges it held the supplier’s reference for the booking the change creates, and no route takes it as input:exchange_statusreads bybooking_refandlast_name.
exchange_shopdeclares each offer’s itinerary and fare:legs[]withstops,duration_minutesandsegments[], whose members use the names of a flight search segment (airline,operating_carrier,flight_number,departure_airport,departure_time,arrival_airport,arrival_time,duration_minutes), the fare per segment (cabin_name,fare_brand_key,fare_basis_code,rbd) and the fare per offer (fare_basis_codes,booking_classes,cabin). Exchange times are local wall-clock time with no UTC offset, unlike a flight search segment’s.exchange_pricedeclares the new fare’s terms and baggage:new_fare_detailsaddsfare_brand_name,fare_brand_code,fare_basis_codes,endorsements,is_refundable,is_changeable,refund_policy,change_policy,checked_baggageandcarry_on_baggage, and the extra bag options declareis_included,segment_idandjourney_id.fare_change_noticeis declared.
0.58.0
Released 2026-10-14. AddedGET /v1/hotel_reviews/{hotel_id}: the guest score and review count, a summary of what guests praise and criticise, a score per category (cleanliness, location, staff and others) and a page of recent reviews, newest first, each with its headline, score, pros and cons, date and language. Page withlimit(1 to 50, default 10) andoffset. It takes the samehotel_idashotel_details.hotel_detailsaddsrating,review_count,child_allowed,pets_allowed,facility_items,rooms[].amenity_items,rooms[].max_adultsandrooms[].max_children, andchild_allowedandpets_allowedon the policy.max_adultsandmax_childrenare how many adults and children a room accepts;max_children: 0means the room does not take children.facility_itemspairs each facility with its Jinko facility dictionary id, the valuefacility_idsaccepts onhotel_search; a facility without a dictionary id stays infacilitiesonly.rooms[].amenity_itemscarries room amenity ids, a separate list from the facility dictionary.- 422
MISSING_CUSTOMER_DETAILSoncheckoutandbookcarriesmissing_fieldsandmissing_by_domainwhen the platform can name what the booking still needs, such as the passport fields an airline requires: the field names asupsert_travelerstakes them (passport_numberand others), and the same names grouped by product (flight). Both are absent when the refusal names no field. Send the named fields withupsert_travelers.
0.57.1
Released 2026-10-13. Changed- A checkout quote is payable for up to one hour.
expires_aton the checkout answer is at most one hour after the checkout call (it was about fifteen minutes), and earlier when an offer in the trip has a shorter deadline of its own: some airline fares last twenty minutes from their search. A payment submitted after it is still refused with 410QUOTE_EXPIRED.
0.57.0
Released 2026-10-13. This version was first served on 2026-10-13 at 19:34 UTC under the number 1.0.0 and renumbered 0.57.0 at 20:19 UTC; the contract is the same. Breaking- Supplier fields are removed from responses:
providerandprovider_nameon flight offers;provider_statusesonflight_search, in success and error bodies;provideron hotels, onsearch_scopeand itsproviders[], and onhotel_details,hotel_cancelandflight_refund_preview. The raw supplier status word is removed too:provider_statusonbookings[]entries and on refund status, and inside theproviderobject ofhotel_cancel_statusandflight_refund_status, which keepsstate,referencesanddocuments. flight_searchno longer answersresult: "provider_error". A search that completes without a match answersresult: "no_matches"as before. A search that could not be completed at all answers an error:UPSTREAM_REJECTED,UPSTREAM_ERROR,UPSTREAM_UNAVAILABLEorUPSTREAM_TIMEOUT. Offers that were found are returned even when part of the search failed.- Servicing inputs that named the supplier or its references are removed:
provideron the flight refund and exchange requests and onhotel_cancel,order_id,provider_referenceandprovider_booking_id. A request carrying one is refused with 422BAD_REQUESTnaming the field. Name the booking withbooking_ref, which is now required, and the item fromget_booking(booked_item_id, nameditem_iduntil 0.74.0). - The two
enable_*query parameters onhotel_searchthat turned individual hotel suppliers on or off are removed. A request carrying either is refused with 422 naming the parameter.
payment_typeson a hotel rate is a closed enum:pay_now,pay_at_property,deposit.hotel_refand an ancillaryoffer_idare opaque. Pass them back exactly as received; their format is not part of the contract.hotel_detailstakes ahotel_refas received, or a plainhotel_id.hotel_refwas later removed in 0.72.0.- The supplier-facing error codes carry fixed messages.
UPSTREAM_REJECTED,UPSTREAM_UNAVAILABLE,UPSTREAM_TIMEOUT,UPSTREAM_ERROR,RATE_LIMITED,OFFER_UNAVAILABLEandOFFER_EXPIREDalways carry the same message and never upstream text; see Messages on supplier failures. A 429 documentsRetry-After. - Upstream statuses follow the error categories. A 503 from the platform is answered 503
UPSTREAM_UNAVAILABLEwith itsRetry-After, and a 504 is answered 504UPSTREAM_TIMEOUT; both used to be answered 502UPSTREAM_ERROR. A 429 carries the platform’sRetry-After. A hotel refusal is 502UPSTREAM_REJECTED, as a flight refusal already was. - Refusals that used to quote the supplier carry fixed sentences: 409
not_cancellable(“This booking cannot be cancelled online. Contact Jinko support.”), 409not_exchangeable(“This booking cannot be exchanged online. Contact Jinko support.”), 400invalid_exchange_requestandpartial_exchange_unsupported(uppercase since 0.74.0) from the supplier (“This exchange cannot be processed as requested. Change the selected flights or contact Jinko support.”), andmanual_reasonwhere it would be the supplier’s own words (“This request needs manual handling by Jinko support.”). - The other supplier refusals carry fixed sentences too: 400 on
flight_search(search and price check) and onhotel_searchwhen a supplier declined the inputs (“The request was declined for these inputs. Check the dates, places and travellers, then retry.”), 422 oncar_search(“The rental request was declined. Try another vehicle, location or time.”), and a quote’sfailure_messagewhere it would carry the supplier’s words (“The booking could not be completed. Contact Jinko support.”).warningsonrefund_checkand on the exchange answers leave out notes the supplier sends as free text without a code. flight_price_adviceanswers a refusal of its inputs as 400 or 422BAD_REQUESTwith the platform’s sentence. It used to answer 502UPSTREAM_REJECTED.- Descriptions and examples in the contract no longer name a supplier.
