# AUTOGENERATED — synced verbatim from jinko-api/public-api.yaml; edit the spec in jinko-api, not this copy.
openapi: 3.0.0
info:
  title: Jinko Public API
  version: 0.87.0
  description: >-
    Curated public REST surface for Jinko. Authenticated with jnk_ API keys. See
    https://docs.gojinko.com for guides.


    ### Per-end-user attribution


    On booking calls you may send an optional `X-End-User-Id` request header to
    attribute the booking to one of your own end users (for per-end-user
    attribution and rate-limiting). The value is an **opaque, tenant-scoped**
    identifier that you choose — not a Jinko account id. Omit it to book as the
    tenant. Values prefixed `user_` or `org_` are rejected.
servers:
  - url: https://api.gojinko.com
    description: Production
  - url: https://api.sandbox.gojinko.com
    description: Sandbox
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    BearerAuth:
      type: http
      scheme: bearer
  schemas:
    MoneyValue:
      type: object
      properties:
        value:
          type: integer
          description: "Integer amount in MINOR units at the ISO 4217 digits of
            `currency`: divide by 10 ** decimal_places to get the amount. Signed
            where the field says so (a price change delta)."
          example: 41250
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          description: ISO 4217 currency code.
          example: USD
        decimal_places:
          type: integer
          description: The ISO 4217 digits of `currency` (2 for USD/EUR, 0 for JPY/KRW, 3
            for BHD/KWD), and the scale of `value`.
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount at `decimal_places`, e.g. "USD 412.50". Show
            this; compute with `value`.'
          example: USD 412.50
      required:
        - value
        - currency
        - decimal_places
        - display
      description: "Money as every new field carries it: `value` is an INTEGER in
        minor units at the ISO 4217 digits of `currency` (`decimal_places`), and
        `display` is the same figure ready to show. All four members are always
        present; a figure the platform does not know is absent, never `{value:
        0}`. New integrations read the `*_money` fields (and `value` on the
        objects that carry it); the two-scale rule described on `Money` applies
        only to the deprecated fields."
    StopInfo:
      type: object
      properties:
        airport_code:
          type: string
          description: IATA code of the airport where the leg stops.
          example: DFW
        duration_minutes:
          type: number
          description: Layover length in minutes (arrival of the inbound segment to
            departure of the next). Omitted when the upstream times cannot be
            resolved.
          example: 95
    CachedSegment:
      type: object
      properties:
        airline:
          type: string
          description: IATA code of the MARKETING carrier — whose flight number you booked.
          example: AA
        airline_name:
          type: string
          example: American Airlines
        flight_number:
          type: string
          description: Provider flight number, forwarded unchanged. Depending on the
            upstream provider it may be a bare number such as `460` or a
            composed designator such as `AS460`; the carrier code is also
            carried separately when known.
          example: "460"
        departure_airport:
          type: string
          example: JFK
        departure_city:
          type: string
          example: New York
        departure_time:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. On the rare
            airport whose timezone the platform does not know, a cached time
            keeps its local wall-clock digits but is written as UTC (`…Z`), so
            it reads as an instant that is off by that airport’s true offset;
            the offset is never omitted here, unlike on a live leg. The
            `*_local` fields of a booked or exchanged itinerary are NOT this:
            those carry wall-clock time with no offset, by design."
          example: "2026-09-23T11:55:00-04:00"
        arrival_airport:
          type: string
          example: DFW
        arrival_city:
          type: string
          example: Dallas
        arrival_time:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. On the rare
            airport whose timezone the platform does not know, a cached time
            keeps its local wall-clock digits but is written as UTC (`…Z`), so
            it reads as an instant that is off by that airport’s true offset;
            the offset is never omitted here, unlike on a live leg. The
            `*_local` fields of a booked or exchanged itinerary are NOT this:
            those carry wall-clock time with no offset, by design."
          example: "2026-09-23T15:10:00-05:00"
        duration_minutes:
          type: number
          example: 255
        layover_minutes:
          type: number
          description: Wait between this segment’s arrival and the next departure. Absent
            on the last segment of a leg, and whenever the upstream times could
            not be resolved.
          example: 95
        operating_carrier:
          type: string
          description: "IATA code of the carrier that actually OPERATES the segment, when
            the cached fare recorded one. A value differing from `airline` is a
            codeshare the passenger must be told about. Equality is not
            guaranteed to be stated: the field is absent when the cached record
            carries no operating carrier, which says nothing about who operates
            the flight."
          example: MQ
    CachedFlightLeg:
      type: object
      properties:
        origin:
          type: string
          example: JFK
        destination:
          type: string
          example: LAX
        departure_datetime:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. On the rare
            airport whose timezone the platform does not know, a cached time
            keeps its local wall-clock digits but is written as UTC (`…Z`), so
            it reads as an instant that is off by that airport’s true offset;
            the offset is never omitted here, unlike on a live leg. The
            `*_local` fields of a booked or exchanged itinerary are NOT this:
            those carry wall-clock time with no offset, by design."
          example: "2026-07-15T08:30:00-04:00"
        arrival_datetime:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. On the rare
            airport whose timezone the platform does not know, a cached time
            keeps its local wall-clock digits but is written as UTC (`…Z`), so
            it reads as an instant that is off by that airport’s true offset;
            the offset is never omitted here, unlike on a live leg. The
            `*_local` fields of a booked or exchanged itinerary are NOT this:
            those carry wall-clock time with no offset, by design."
          example: "2026-07-15T11:55:00-07:00"
        duration_minutes:
          type: number
          example: 385
        airline:
          type: string
          example: AA
        airline_name:
          type: string
          example: American Airlines
        stops:
          type: number
          example: 0
        stop_infos:
          type: array
          items:
            $ref: "#/components/schemas/StopInfo"
          description: "Layover detail, one entry per stop, in travel order. Absent when
            the leg is non-stop (`stops: 0`) or when upstream detail is
            incomplete for any stop; `stops` still reports the connection count
            in that case."
          example: &a1
            - airport_code: DFW
              duration_minutes: 95
        segments:
          type: array
          items:
            $ref: "#/components/schemas/CachedSegment"
          description: The flown segments of this leg, in travel order — one per flight. A
            non-stop leg has one. Read `operating_carrier` here to disclose a
            codeshare the cached fare recorded. Absent when the cached row has
            no segment breakdown, in which case `stops` and `stop_infos` are all
            that is known about the leg.
    TimeRange:
      type: object
      properties:
        earliest:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d$
          example: "08:00"
        latest:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d$
          example: "12:00"
      description: 'Inclusive local time-of-day window, 24-hour "HH:MM". Either bound
        may be omitted: only `earliest` means "at or after", only `latest` means
        "at or before".'
    CheckedBaggage:
      type: object
      properties:
        pieces:
          type: integer
          description: Number of bags included at this allowance.
          example: 1
        weight:
          type: number
          description: Weight allowance per bag, in `weight_unit`.
          example: 23
        weight_unit:
          type: string
          description: "`KG` or `LB`. Absent when the provider states no recognised unit."
          example: KG
        dimensions:
          type: string
          description: Size limit as the carrier states it. Free text, not a parseable
            measurement.
          example: 158 cm linear
        description:
          type: string
          description: "Text the platform writes from the allowance, not the carrier’s own
            prose: for checked bags `1 bag, 23KG each`, `2 checked bags
            included` or `No checked bags included`; for cabin bags `1 carry-on
            bag` or `2 cabin bags`, with ` and 1 personal item` when one is
            included. Present on fares with NO free allowance too (`No checked
            bags included`), so its presence is not evidence a bag is included."
          example: 1 bag, 23KG each
      description: A baggage allowance. Until v0.2.0 this was documented as a string
        while the platform sent this object — clients generated against the old
        spec typed it as text.
    Segment:
      type: object
      properties:
        airline:
          type: string
          description: IATA code of the MARKETING carrier — whose flight number you booked.
          example: AA
        airline_name:
          type: string
          example: American Airlines
        flight_number:
          type: string
          description: "Marketing flight number as the provider sends it on a live offer:
            a bare number such as `460`, without the carrier code, which
            `airline` carries."
          example: "460"
        aircraft:
          type: string
          description: IATA aircraft type code for the equipment scheduled on this
            segment. Absent when the provider reports no equipment; some
            providers never do, so their itineraries carry no `aircraft` at all
            (and are dropped by the `aircraft_types` filter).
          example: 32Q
        departure_airport:
          type: string
          example: JFK
        departure_city:
          type: string
          description: "IATA city code of the departure airport (`NYC` for JFK), from the
            platform’s airport catalog: a code, not a name. Absent when the
            airport is not in the catalog."
          example: NYC
        departure_time:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. The offset is
            a property of this leg/segment shape wherever it appears — a flight
            search, and an itinerary echoed back on a quote or trip read — not
            of the search response alone. On the rare airport whose timezone the
            platform does not know, the offset is omitted and the value is local
            wall-clock time. The `*_local` fields of a booked or exchanged
            itinerary are NOT this: those carry wall-clock time with no offset,
            by design."
          example: "2026-09-23T11:55:00-04:00"
        arrival_airport:
          type: string
          example: DFW
        arrival_city:
          type: string
          description: "IATA city code of the arrival airport (`CHI` for ORD), from the
            platform’s airport catalog: a code, not a name. Absent when the
            airport is not in the catalog."
          example: DFW
        arrival_time:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. The offset is
            a property of this leg/segment shape wherever it appears — a flight
            search, and an itinerary echoed back on a quote or trip read — not
            of the search response alone. On the rare airport whose timezone the
            platform does not know, the offset is omitted and the value is local
            wall-clock time. The `*_local` fields of a booked or exchanged
            itinerary are NOT this: those carry wall-clock time with no offset,
            by design."
          example: "2026-09-23T15:10:00-05:00"
        duration_minutes:
          type: number
          example: 255
        layover_minutes:
          type: number
          description: Wait between this segment’s arrival and the next departure. Absent
            on the last segment of a leg, and whenever the upstream times could
            not be resolved.
          example: 95
        operating_carrier:
          type: string
          description: "IATA code of the carrier that actually OPERATES the segment. A
            value differing from `airline` is a codeshare the passenger must be
            told about. Whether equality is stated depends on the provider: some
            always send it, including when it equals `airline`; others send it
            only when they disclose an operating carrier, so an absent value
            says nothing about who operates the flight."
          example: MQ
    FlightLeg:
      type: object
      properties:
        origin:
          type: string
          example: JFK
        destination:
          type: string
          example: LAX
        departure_datetime:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. The offset is
            a property of this leg/segment shape wherever it appears — a flight
            search, and an itinerary echoed back on a quote or trip read — not
            of the search response alone. On the rare airport whose timezone the
            platform does not know, the offset is omitted and the value is local
            wall-clock time. The `*_local` fields of a booked or exchanged
            itinerary are NOT this: those carry wall-clock time with no offset,
            by design."
          example: "2026-07-15T08:30:00-04:00"
        arrival_datetime:
          type: string
          description: "Local time at the airport, RFC 3339 with that airport’s UTC offset
            (e.g. `2026-09-23T11:55:00-04:00`). Parse it as an instant; do not
            assume UTC and do not compare two of these as strings. The offset is
            a property of this leg/segment shape wherever it appears — a flight
            search, and an itinerary echoed back on a quote or trip read — not
            of the search response alone. On the rare airport whose timezone the
            platform does not know, the offset is omitted and the value is local
            wall-clock time. The `*_local` fields of a booked or exchanged
            itinerary are NOT this: those carry wall-clock time with no offset,
            by design."
          example: "2026-07-15T11:55:00-07:00"
        duration_minutes:
          type: number
          example: 385
        airline:
          type: string
          example: AA
        airline_name:
          type: string
          example: American Airlines
        stops:
          type: number
          example: 0
        stop_infos:
          type: array
          items:
            $ref: "#/components/schemas/StopInfo"
          description: "Layover detail, one entry per stop, in travel order. Absent when
            the leg is non-stop (`stops: 0`) or when upstream detail is
            incomplete for any stop; `stops` still reports the connection count
            in that case."
          example: *a1
        segments:
          type: array
          items:
            $ref: "#/components/schemas/Segment"
          description: The flown segments of this leg, in travel order — one per aircraft.
            A non-stop leg has one. Read `operating_carrier` here to disclose
            codeshares. Absent when the provider returned no segment breakdown,
            in which case `stops` and `stop_infos` are all that is known about
            the leg.
    Amount:
      type: object
      properties:
        value:
          type: integer
          description: "Integer amount in MINOR units, always paired with decimal_places —
            divide by 10 ** decimal_places to display. Example: value 15977 with
            decimal_places 2 is 159.77 USD. Rendering this field directly shows
            prices 100x too high for 2-decimal currencies."
          example: 41250
        currency:
          type: string
          description: ISO 4217 currency code.
          example: USD
        decimal_places:
          type: integer
          description: "Scale of the integer value/amount: display = integer / 10 **
            decimal_places. Always sent alongside minor-unit amounts. Usually
            the ISO 4217 digits of the currency (2 for USD/EUR/GBP, 0 for
            JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices can carry
            a different scale — ALWAYS use the decimal_places sent with the
            amount, never a hardcoded 2. Only if the field is genuinely absent
            on a value-shaped object, fall back to the ISO digits for the
            currency."
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount, e.g. "USD 159.77". With decimal_places it is
            written at exactly that scale (value 1561500, JPY, decimal_places 2
            is "JPY 15615.00"); without, at the ISO digits of the currency. Show
            this; compute with the number. Absent when the figure is not money
            (a cancellation step expressed as a percent or a number of nights)
            or could not be read unambiguously.'
          example: USD 412.50
      required:
        - value
        - currency
    Itinerary:
      type: object
      properties:
        offer_token:
          type: string
          description: "This cached itinerary’s offer token: pass it unchanged as
            `offer_token` to `POST /v1/flight_search` to price-check it live. It
            cannot be added to a trip."
          example: es-VVN8QUZ8MjAyNzA2MTU6QUY6Nzo6WXwyMDI3MDYyMjpBRjo2OjpZ
        id:
          type: string
          description: "Deprecated: use `offer_token` instead. Same value."
          example: es-VVN8QUZ8MjAyNzA2MTU6QUY6Nzo6WXwyMDI3MDYyMjpBRjo2OjpZ
          deprecated: true
        origin:
          type: object
          properties:
            code:
              type: string
            name:
              type: string
          required:
            - code
          example:
            code: JFK
            name: New York John F. Kennedy
        destination:
          type: object
          properties:
            code:
              type: string
            name:
              type: string
          required:
            - code
          example:
            code: CDG
            name: Paris Charles de Gaulle
        total:
          allOf:
            - $ref: "#/components/schemas/Amount"
            - description: "One adult's fare (`priced_for: \"one_adult\"`): the cache holds
                one-adult fares only. To price the whole party, pass
                `offer_token` to `POST /v1/flight_search` with the party."
        cabin_class:
          type: string
          example: economy
        outbound:
          allOf:
            - $ref: "#/components/schemas/CachedFlightLeg"
            - description: The outbound journey this price is for — the departure date and
                time are in `departure_datetime`. Absent on cached rows stored
                before the platform kept the flown itinerary.
        inbound:
          allOf:
            - $ref: "#/components/schemas/CachedFlightLeg"
            - description: The return journey. Present on a round trip only, and absent on an
                older cached row the same way `outbound` is.
        priced_at:
          type: string
          description: When this price was collected, RFC 3339 UTC. These results come
            from the cache and can be days old — re-price with `flight_search`
            before quoting or booking.
          example: "2026-09-19T03:57:25Z"
      required:
        - offer_token
        - id
        - origin
        - destination
    MonitoredMoney:
      type: object
      properties:
        amount:
          type: number
          description: Alternative to `value` on some endpoints (the two never appear
            together); its scale depends on decimal_places. When this object
            carries decimal_places, amount is an INTEGER in minor units — divide
            by 10 ** decimal_places (e.g. select_ancillaries
            total_with_ancillaries). When there is no decimal_places field,
            amount is a decimal in MAJOR units, safe to display as-is (e.g. trip
            and checkout totals).
        value:
          type: integer
          description: "Integer amount in MINOR units, always paired with decimal_places —
            divide by 10 ** decimal_places to display. Example: value 15977 with
            decimal_places 2 is 159.77 USD. Rendering this field directly shows
            prices 100x too high for 2-decimal currencies."
          example: 41250
        currency:
          type: string
          description: ISO 4217 currency code.
          example: USD
        decimal_places:
          type: integer
          description: "Scale of the integer value/amount: display = integer / 10 **
            decimal_places. Always sent alongside minor-unit amounts. Usually
            the ISO 4217 digits of the currency (2 for USD/EUR/GBP, 0 for
            JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices can carry
            a different scale — ALWAYS use the decimal_places sent with the
            amount, never a hardcoded 2. Only if the field is genuinely absent
            on a value-shaped object, fall back to the ISO digits for the
            currency."
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount, e.g. "USD 159.77". With decimal_places it is
            written at exactly that scale (value 1561500, JPY, decimal_places 2
            is "JPY 15615.00"); without, at the ISO digits of the currency. Show
            this; compute with the number. Absent when the figure is not money
            (a cancellation step expressed as a percent or a number of nights)
            or could not be read unambiguously.'
          example: USD 412.50
    WebhookMoney:
      type: object
      properties:
        amount:
          type: number
          description: Major currency units.
          example: 188.65
        currency:
          type: string
          example: USD
      required:
        - amount
        - currency
      description: "Money as a webhook payload carries it: `amount` in MAJOR currency
        units (188.65, not 18865) beside its ISO currency. This is the trip’s
        money shape, not the integer minor-unit form the post-booking totals use
        — do not divide it."
    WebhookEvent:
      type: string
      enum:
        - booking.processing
        - booking.completed
        - booking.failed
        - booking.partial
        - servicing.completed
        - servicing.exchange_confirmed
        - servicing.ticket_issued
        - servicing.failed
      description: "A booking lifecycle event. `booking.processing` — Payment is
        authorized and the booking is being confirmed with the suppliers. No
        supplier reference exists yet. `booking.completed` — Every item of the
        booking is confirmed and the payment is captured. `booking.failed` — No
        item of the booking could be confirmed. The payment hold is released and
        nothing is charged. `booking.partial` — Payment is captured but only
        some items were confirmed; the trip needs attention. A distinct event,
        so a handler written before it existed can never mistake it for a
        success. `servicing.completed` — A post-booking operation on one booked
        item (a cancellation) is complete and its money is settled. Distinct
        from booking.completed: it reports a booking being undone, not made.
        `servicing.exchange_confirmed` — The supplier confirmed an exchange of
        one booked item. For a flight, the new e-ticket number may follow in
        servicing.ticket_issued. `servicing.ticket_issued` — The new e-ticket
        number of an exchanged flight is available. `servicing.failed` — An
        exchange or a refund could not be completed. The original booking is
        unchanged unless the payload says otherwise."
    SupplierReference:
      type: object
      properties:
        issuer:
          type: string
          description: "Who issued the reference: the airline’s IATA code, the hotel’s
            name, or the rental company’s name."
          example: AF
        reference:
          type: string
          description: The reference itself.
          example: XM9L2K
      required:
        - issuer
        - reference
    PartialBookingItem:
      type: object
      properties:
        item_id:
          type: string
          example: itm_4b91c2
        kind:
          type: string
          description: '"flight", "hotel", "car" or "ground".'
          example: flight
        status:
          type: string
          enum:
            - completed
            - failed
          description: Whether THIS item was booked. At least one of each is what makes it
            partial.
          example: completed
        supplier_references:
          type: array
          items:
            $ref: "#/components/schemas/SupplierReference"
          description: The confirmations the supplier itself issued for this item, on a
            completed item. Absent on a failed item. The Jinko reference is the
            event-level `booking_ref`.
        booking_reference:
          type: string
          description: "Deprecated: use `supplier_references` instead. A confirmation for
            this item; when the airline’s own locator is not known it can hold
            an id only Jinko’s intermediary answers to."
          example: XM9L2K
          deprecated: true
        captured_amount:
          allOf:
            - $ref: "#/components/schemas/WebhookMoney"
            - description: "Deprecated: use `captured_amount_money` instead."
              deprecated: true
        captured_amount_money:
          $ref: "#/components/schemas/MoneyValue"
      required:
        - item_id
        - kind
        - status
      description: One item of a partially fulfilled trip. `status` is this item’s own
        outcome, and at least one `completed` beside one `failed` is what makes
        the booking partial. `captured_amount_money` is what was charged for
        THIS item (`captured_amount`, deprecated, is the same figure in major
        units); a failed item was not charged and carries neither it nor
        `supplier_references`.
    PartialBookingData:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/PartialBookingItem"
          description: Every item on the trip with its own outcome, booked and failed alike.
        captured_total:
          allOf:
            - $ref: "#/components/schemas/WebhookMoney"
            - description: "Deprecated: use `captured_total_money` instead."
              deprecated: true
        captured_total_money:
          $ref: "#/components/schemas/MoneyValue"
      required:
        - items
      description: The `data` object carried by `booking.partial`. `items` lists every
        item on the trip with its own outcome, booked and failed alike.
        `captured_total_money` is what was actually charged — the completed
        items only, NOT the trip total, so reconciling against the original
        quote will not balance. `captured_total` (deprecated) is the same figure
        in major units.
    EmailManageBookingURL:
      type: string
      format: uri
      description: "Jinko web app booking link. Personal data: its query includes the
        traveller’s last name."
    EmailFlightSegment:
      type: object
      properties:
        departure_city_name:
          type: string
          description: Departure city, shown in the layover row.
        departure_airport_name:
          type: string
          description: Departure airport name.
        departure_iata:
          type: string
          description: Departure airport IATA code.
        departure_time:
          type: string
          description: Departure local time, display string.
        arrival_airport_name:
          type: string
          description: Arrival airport name.
        arrival_iata:
          type: string
          description: Arrival airport IATA code.
        arrival_time:
          type: string
          description: Arrival local time, display string.
        duration_formatted:
          type: string
          description: Segment duration, such as 2h 15m.
        flight_number:
          type: string
          description: Marketing flight number.
        aircraft:
          type: string
          description: Aircraft type.
        airline_name:
          type: string
          description: Marketing airline name.
        airline_logo_url:
          type: string
          format: uri
          description: Marketing airline logo URL.
        layover_before:
          type: string
          description: Layover before this segment; omitted on the first.
      description: One flown segment as booking confirmation, cancellation and
        exchange emails show it.
    EmailFlight:
      type: object
      properties:
        label:
          type: string
          description: "Leg heading: Outbound, Return, or Leg N of M."
        departure_date:
          type: string
          description: Leg departure date, display string.
        cabin_class:
          type: string
          description: Cabin class label, such as Economy.
        segments:
          type: array
          items:
            $ref: "#/components/schemas/EmailFlightSegment"
          description: Segments in flown order.
      description: One leg as booking confirmation, cancellation and exchange emails
        show it.
    EmailFlightHeadline:
      type: object
      properties:
        destination_name:
          type: string
          description: Destination city of the first leg, as in the headline.
      description: The first leg as cancellation and exchange headlines name it.
    EmailPassenger:
      type: object
      properties:
        first_name:
          type: string
          description: First name. Personal data.
        last_name:
          type: string
          description: Last name. Personal data.
        type:
          type: string
          description: Adult, Child or Infant.
        date_of_birth:
          type: string
          description: Date of birth as stored. Personal data.
        ticket_number:
          type: string
          description: E-ticket number, set where the email lists it per traveller (flight
            exchange). Personal data.
      description: A traveller on booking confirmation, flight cancellation and
        exchange emails. Personal data.
    EmailRefund:
      type: object
      properties:
        amount_formatted:
          type: string
          description: Refund settled for this item; omitted when none is settled.
        original_amount_formatted:
          type: string
          description: What was originally paid.
        card_brand:
          type: string
          description: Brand of the card refunded to.
        last_four:
          type: string
          description: Last four of that card. Sensitive payment data.
        method_label:
          type: string
          description: Wallet refunded to when there is no card identity.
        eta_label:
          type: string
          description: When the refund should land, such as within 5–10 business days.
        issued_at:
          type: string
          description: Refund issue date. Not sent today.
        fee_formatted:
          type: string
          description: Cancellation fee or penalty, display string.
        fee_label:
          type: string
          description: Fee label.
      description: Refund block of a cancellation email.
    FlightCancellationEmailContent:
      type: object
      properties:
        pending_seat_refunds:
          type: array
          items:
            type: string
          description: Seat-refund notes. Not sent today in webhook events.
        pnr:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        reason:
          type: string
          description: Customer’s free-text reason. Not sent today.
        legs:
          type: array
          items:
            $ref: "#/components/schemas/EmailFlight"
          description: Cancelled itinerary; omitted after an exchange superseded it.
        outbound_flight:
          $ref: "#/components/schemas/EmailFlightHeadline"
        passengers:
          type: array
          items:
            $ref: "#/components/schemas/EmailPassenger"
          description: Passengers. Personal data.
        refund:
          $ref: "#/components/schemas/EmailRefund"
        rebook_url:
          type: string
          format: uri
          description: Rebook link. Not sent today.
      description: What the default flight cancellation email shows, including the
        first cancelled leg in its headline and the refund block. Values are
        display strings as the email shows them.
    BookingCalendarFile:
      type: object
      properties:
        method:
          type: string
          description: "The iTIP method (RFC 5546) this file carries: `REQUEST` for the
            events the booking still holds, `CANCEL` for the ones it no longer
            does. One file carries exactly one method — a booking that both
            retires and confirms flights, which is what an exchange does, comes
            back as two files rather than one mixed one."
          example: REQUEST
        filename:
          type: string
          description: The name the confirmation or cancellation email attached this same
            file under.
          example: jinko-JNK-A0AUR2.ics
        content_type:
          type: string
          description: "The media type, including the `method` parameter. Attach or serve
            the file under this exact value: the method parameter is what makes
            a mail client act on the file instead of storing it as a plain
            attachment."
          example: text/calendar; charset=utf-8; method=REQUEST
        content:
          type: string
          description: The iCalendar file itself. Real CRLF line endings, as iCalendar
            requires — the example escapes them only so it can be read here.
            Byte-identical to what the email carried for the current state of
            this booking.
          example: BEGIN:VCALENDAR\r\nVERSION:2.0\r\n…\r\nEND:VCALENDAR\r\n
    BookingCalendar:
      type: object
      properties:
        files:
          type: array
          items:
            $ref: "#/components/schemas/BookingCalendarFile"
          description: "The iCalendar files this booking is carried in, cancellation first
            and then invitation — the order the emails attach them in. Never
            empty: a booking with nothing to put in a calendar omits `calendar`
            altogether."
      description: The calendar entries for this booking, as iCalendar files. Absent —
        not null, and never an empty list — when the booking holds no flight and
        no hotel, and whenever the files could not be built.
    FlightCancellationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - flight-cancellation
        content:
          $ref: "#/components/schemas/FlightCancellationEmailContent"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      required:
        - subject
        - template
        - content
      description: Flight cancellation or void. Calendar contains the attached .ics
        files, omitted when none are attached or there is no recipient.
    EmailHotelAddress:
      type: object
      properties:
        formatted:
          type: string
          description: Address on one line.
        phone:
          type: string
          description: Property phone number.
        map_url:
          type: string
          format: uri
          description: Map link for the property.
      description: Hotel address block.
    EmailHotelSummary:
      type: object
      properties:
        name:
          type: string
          description: Hotel name.
        image_url:
          type: string
          format: uri
          description: Main photo URL.
        address:
          $ref: "#/components/schemas/EmailHotelAddress"
      description: The property and address as the hotel cancellation email shows them.
    EmailHotelStay:
      type: object
      properties:
        check_in_date:
          type: string
          description: Check-in date, display string; raw YYYY-MM-DD on hotel cancellation.
        check_in_time:
          type: string
          description: Check-in time. Not sent today.
        check_out_date:
          type: string
          description: Check-out date, displayed in the same format as check_in_date.
        check_out_time:
          type: string
          description: Check-out time. Not sent today.
        duration_label:
          type: string
          description: Length of stay, such as 3 nights.
      description: Check-in and check-out.
    EmailHotelRoom:
      type: object
      properties:
        name:
          type: string
          description: Room name.
        count_label:
          type: string
          description: Room count, such as 1 room.
        occupancy_label:
          type: string
          description: Occupancy, such as 2 guests.
      description: The booked room.
    EmailGuestName:
      type: object
      properties:
        first_name:
          type: string
          description: First name. Personal data.
        last_name:
          type: string
          description: Last name. Personal data.
      description: A guest on the hotel cancellation email. Personal data.
    HotelCancellationEmailContent:
      type: object
      properties:
        pnr:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        cancelled_at:
          type: string
          description: Completion date, display string.
        reason:
          type: string
          description: Customer’s free-text reason. Not sent today.
        hotel:
          $ref: "#/components/schemas/EmailHotelSummary"
        stay:
          $ref: "#/components/schemas/EmailHotelStay"
        room:
          $ref: "#/components/schemas/EmailHotelRoom"
        guests:
          type: array
          items:
            $ref: "#/components/schemas/EmailGuestName"
          description: Guests. Personal data.
        refund:
          $ref: "#/components/schemas/EmailRefund"
        rebook_url:
          type: string
          format: uri
          description: Rebook link. Not sent today.
        applied_tier_label:
          type: string
          description: Label of the cancellation tier that applied. Not sent today.
        applied_tier_sublabel:
          type: string
          description: Sublabel of the cancellation tier that applied. Not sent today.
      description: What the default hotel cancellation email shows, including
        property, room, refund and applied cancellation tier labels. Stay dates
        are the raw stored strings. Values are display strings as the email
        shows them.
    HotelCancellationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - hotel-cancellation
        content:
          $ref: "#/components/schemas/HotelCancellationEmailContent"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      required:
        - subject
        - template
        - content
      description: Hotel cancellation. Calendar contains the attached .ics files,
        omitted when none are attached or there is no recipient.
    EmailCarStop:
      type: object
      properties:
        branch_name:
          type: string
          description: Rental branch.
        address:
          type: string
          description: Branch address with city.
        phone:
          type: string
          description: Branch phone.
        date_time_label:
          type: string
          description: Branch-local date and time with the zone in the string.
      description: One end of a rental.
    EmailCarExtra:
      type: object
      properties:
        label:
          type: string
          description: Extra with quantity, such as Infant seat × 2.
        detail:
          type: string
          description: Money line, such as €30.00 · paid now; omitted on cancellation.
      description: One rate extra.
    EmailCar:
      type: object
      properties:
        vehicle_name:
          type: string
          description: Vehicle, with or similar when only the class is guaranteed.
        vehicle_class:
          type: string
          description: Class line, such as Economy · Automatic · Petrol.
        supplier_name:
          type: string
          description: Rental company the driver meets.
        supplier_logo_url:
          type: string
          format: uri
          description: Rental company logo URL.
        pick_up:
          $ref: "#/components/schemas/EmailCarStop"
        drop_off:
          $ref: "#/components/schemas/EmailCarStop"
        pay_now_formatted:
          type: string
          description: Part collected at checkout; authorization-time email only.
        due_at_desk_formatted:
          type: string
          description: Amount due at the desk in its currency; never part of a charged
            total.
        extras:
          type: array
          items:
            $ref: "#/components/schemas/EmailCarExtra"
          description: Rate extras in the order chosen.
      description: A self-drive rental, including pick-up and drop-off branches and times.
    EmailGuest:
      type: object
      properties:
        first_name:
          type: string
          description: First name or an unnamed-occupant line such as 1 adult, 1 child
            (age 5). Personal data.
        last_name:
          type: string
          description: Last name; a minor’s includes (age N) on hotel confirmations.
            Personal data.
        room_label:
          type: string
          description: Room the guest occupies on a multi-room stay.
      description: A hotel guest or car driver on hotel booking, car cancellation and
        car exchange emails. Personal data.
    CarCancellationEmailContent:
      type: object
      properties:
        pnr:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        confirmation_code:
          type: string
          description: Rental supplier’s reservation number.
        cancelled_at:
          type: string
          description: Completion date, display string.
        reason:
          type: string
          description: Customer’s free-text reason. Not sent today in webhook events.
        car:
          $ref: "#/components/schemas/EmailCar"
        drivers:
          type: array
          items:
            $ref: "#/components/schemas/EmailGuest"
          description: Drivers. Personal data.
        refund:
          $ref: "#/components/schemas/EmailRefund"
        refund_pending_review:
          type: boolean
          description: Cancelled, with the refund amount awaiting human review.
        fee_unknown:
          type: boolean
          description: No fee schedule could be established.
        non_refundable:
          type: boolean
          description: The fee consumed the whole charge; nothing is returned.
      required:
        - refund_pending_review
        - fee_unknown
        - non_refundable
      description: What the default car cancellation email shows for the cancelled
        rental. Values are display strings as the email shows them; booleans are
        always sent. Pending refund review omits refund and sets non_refundable
        to false.
    CarCancellationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - car-cancellation
        content:
          $ref: "#/components/schemas/CarCancellationEmailContent"
      required:
        - subject
        - template
        - content
      description: Car rental cancellation. This email attaches no calendar.
    ServicingCompletedData:
      type: object
      properties:
        operation:
          type: string
          description: The operation that finished ("svc_…"), the same handle the commit
            answered and the status routes take. Absent when the cancellation
            ran on an older path that has no such handle.
          example: svc_8cd41f
        operation_kind:
          type: string
          description: What the operation did, e.g. `cancel`.
          example: cancel
        booked_item_id:
          type: string
          description: The booked item the operation acted on — `booked_item_id` on
            get_booking.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        item:
          type: integer
          description: "Deprecated: use `booked_item_id` instead. The booked item as an
            integer."
          example: 9182
          deprecated: true
        state:
          type: string
          description: "Always `succeeded`: the event is sent only when the operation
            succeeded."
          example: succeeded
        refund:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - nullable: true
        penalty:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - nullable: true
        booking_ref:
          type: string
          example: JNK-ABC123
        servicing_event:
          type: string
          description: The event name again, `servicing.completed`.
          example: servicing.completed
        manage_booking_url:
          $ref: "#/components/schemas/EmailManageBookingURL"
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/FlightCancellationCustomerEmail"
              - $ref: "#/components/schemas/HotelCancellationCustomerEmail"
              - $ref: "#/components/schemas/CarCancellationCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                flight-cancellation: "#/components/schemas/FlightCancellationCustomerEmail"
                hotel-cancellation: "#/components/schemas/HotelCancellationCustomerEmail"
                car-cancellation: "#/components/schemas/CarCancellationCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      required:
        - operation_kind
        - item
        - state
        - booking_ref
        - servicing_event
      description: The `data` object carried by `servicing.completed`. `refund` is
        what the payment provider settled back to the customer for this item;
        `penalty` is the supplier fee the customer agreed to. Either is `null`
        when the operation carries no such figure — which is not zero. The
        cancellation email is included when available. Its manage-booking link
        is not sent today.
    BookingFailedEmailContent:
      type: object
      properties:
        card_brand:
          type: string
          description: Brand of the card whose hold was released.
        last_four:
          type: string
          description: Last four of that card. Sensitive payment data.
        method_label:
          type: string
          description: Wallet name when there is no card identity.
        amount_formatted:
          type: string
          description: Amount held and not charged, display string.
        provider_noun:
          type: string
          description: "Who refused: airline, hotel, transport operator, rental company,
            or carrier."
        product_noun:
          type: string
          description: "What failed: flight, stay, journey, car, or booking."
        reason_code:
          type: string
          description: "Deprecated: use `failure_reason` instead. The failure code
            selecting the email copy, in the platform’s stored words
            (`offer_not_available` where `failure_reason` says
            `offer_unavailable`). Omitted when unclassified."
          deprecated: true
        failure_reason:
          type: string
          description: "The failure code selecting the email copy, in the words of the
            `booking.failed` data: specific copy exists for price_changed and
            offer_unavailable. Omitted when unclassified. May differ from
            data.failure_reason, which describes the whole trip."
        product_name:
          type: string
          description: Hotel name when exactly one hotel item failed.
      description: What the booking failure email shows, including the resolved
        provider and product nouns. Values are display strings as the email
        shows them.
    BookingFailedCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - booking-failed
        content:
          $ref: "#/components/schemas/BookingFailedEmailContent"
      required:
        - subject
        - template
        - content
      description: Booking could not be completed; hold released. This email attaches
        no calendar.
    BookingFailedData:
      type: object
      properties:
        failure_reason:
          type: string
          enum:
            - price_changed
            - offer_unavailable
            - booking_not_created
            - booking_cancelled_at_provider
          description: Curated failure code; omitted when unclassified.
        failure_message:
          type: string
          description: Customer sentence for price_changed and offer_unavailable only.
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/BookingFailedCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                booking-failed: "#/components/schemas/BookingFailedCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      description: Booking failure details and the booking failure email. Its
        content.reason_code may differ from failure_reason. The email can be
        present even when no curated failure code exists.
    EmailFareConditions:
      type: object
      properties:
        refund_policy:
          type: string
          description: Refund policy sentence.
        change_policy:
          type: string
          description: Change policy sentence.
        carry_on_baggage:
          type: string
          description: Carry-on allowance.
        checked_baggage:
          type: string
          description: Checked baggage allowance.
        exchange_policy:
          type: string
          description: Exchangeable or Non-exchangeable for ground transport.
        seat_reservation:
          type: string
          description: Ground seat reservation policy. Not sent today.
        bike_policy:
          type: string
          description: Ground bike policy. Not sent today.
        pet_policy:
          type: string
          description: Ground pet policy. Not sent today.
      description: "Fare conditions on a booking confirmation item: flight fields on a
        flight, ground fields on a train."
    EmailBookedSeat:
      type: object
      properties:
        seat_number:
          type: string
          description: Seat, such as 14C.
        passenger_name:
          type: string
          description: Passenger the seat is for. Personal data.
        segment_label:
          type: string
          description: Segment, such as CDG → JFK.
        status:
          type: string
          description: "Outcome code: CONFIRMED, PENDING or FAILED."
        price_formatted:
          type: string
          description: Seat price, display string; omitted for an included seat.
        status_label:
          type: string
          description: Outcome label shown to the traveller.
      description: One seat selection and its airline outcome.
    EmailBookedBag:
      type: object
      properties:
        label:
          type: string
          description: Bag label with weight.
        quantity:
          type: integer
          minimum: 1
          description: Number of bags; always sent.
        status_label:
          type: string
          description: Outcome label shown to the traveller.
        price_formatted:
          type: string
          description: Bag price, display string.
      required:
        - quantity
      description: One purchased bag and its airline outcome.
    EmailHotel:
      type: object
      properties:
        name:
          type: string
          description: Hotel name.
        image_url:
          type: string
          format: uri
          description: Main photo URL.
        stars_label:
          type: string
          description: Rating as glyphs, such as ★★★★.
        lodging_type:
          type: string
          description: Accommodation type, such as Aparthotel.
        address:
          $ref: "#/components/schemas/EmailHotelAddress"
      description: The property and address as booking confirmation and hotel
        confirmation emails show them.
    EmailCancellationTier:
      type: object
      properties:
        label:
          type: string
          description: Tier label, such as Free cancellation.
        deadline_label:
          type: string
          description: Tier deadline, display string.
        sublabel:
          type: string
          description: Explanatory sentence under the label.
      description: One row of the hotel cancellation timeline.
    EmailHotelPolicy:
      type: object
      properties:
        title:
          type: string
          description: Row title.
        body:
          type: string
          description: Row text.
      description: "One titled policy row: board, rate information, taxes paid at the
        hotel, total paid, payment or room cancellation."
    EmailTrainSegment:
      type: object
      properties:
        operator_name:
          type: string
          description: Carrier or operator.
        train_type:
          type: string
          description: Transport mode.
        train_number:
          type: string
          description: Service number. Not sent today.
        origin_station_name:
          type: string
          description: Departure station.
        origin_city_name:
          type: string
          description: Departure city. Not sent today.
        destination_station_name:
          type: string
          description: Arrival station.
        destination_city_name:
          type: string
          description: Arrival city. Not sent today.
        departure_time_label:
          type: string
          description: Departure time, display string.
        arrival_time_label:
          type: string
          description: Arrival time, display string.
        duration_formatted:
          type: string
          description: Duration, display string; authorization-time email only.
      description: One ground transport segment.
    EmailTrain:
      type: object
      properties:
        departure_date_label:
          type: string
          description: Journey date, display string.
        travel_class:
          type: string
          description: Fare or class label.
        segments:
          type: array
          items:
            $ref: "#/components/schemas/EmailTrainSegment"
          description: Segments of the journey.
      description: "A ground transport journey: rail, coach or ferry."
    EmailBookingItem:
      type: object
      properties:
        kind:
          type: string
          enum:
            - flight
            - hotel
            - train
            - car
          description: Product kind; train is ground transport.
        legs:
          type: array
          items:
            $ref: "#/components/schemas/EmailFlight"
          description: Flight legs in flown order.
        fare_conditions:
          $ref: "#/components/schemas/EmailFareConditions"
        booked_seats:
          type: array
          items:
            $ref: "#/components/schemas/EmailBookedSeat"
          description: Seat outcomes for a flight.
        booked_bags:
          type: array
          items:
            $ref: "#/components/schemas/EmailBookedBag"
          description: Bag outcomes for a flight.
        hotel:
          $ref: "#/components/schemas/EmailHotel"
        stay:
          $ref: "#/components/schemas/EmailHotelStay"
        room:
          $ref: "#/components/schemas/EmailHotelRoom"
        cancellation_tiers:
          type: array
          items:
            $ref: "#/components/schemas/EmailCancellationTier"
          description: Hotel cancellation timeline.
        cancellation_text:
          type: string
          description: Hotel cancellation summary, shown when there are no tiers.
        policies:
          type: array
          items:
            $ref: "#/components/schemas/EmailHotelPolicy"
          description: Hotel policy rows.
        train:
          $ref: "#/components/schemas/EmailTrain"
        car:
          $ref: "#/components/schemas/EmailCar"
      required:
        - kind
      description: "One product covered by a booking confirmation email. Only fields
        of its kind are present: flight legs and fare conditions, hotel
        property/stay/room, ground journey or car rental."
    EmailChargeLine:
      type: object
      properties:
        label:
          type: string
          description: Line label, such as Fare difference.
        amount_formatted:
          type: string
          description: Line amount, display string.
      description: One charges line.
    EmailChargesBreakdown:
      type: object
      properties:
        lines:
          type: array
          items:
            $ref: "#/components/schemas/EmailChargeLine"
          description: Lines in display order.
        total_formatted:
          type: string
          description: Total, display string.
        total_label:
          type: string
          description: Total label, such as Total charged or Total refunded.
      description: Charges section of the email.
    EmailPayment:
      type: object
      properties:
        card_brand:
          type: string
          description: Card brand, such as Visa.
        last_four:
          type: string
          description: Card last four. Sensitive payment data.
        method_label:
          type: string
          description: Wallet name when there is no card identity, such as Stripe Link.
        status:
          type: string
          enum:
            - authorized
            - charged
          description: 'Which label the email shows: `authorized` ("Authorized on" or
            "Authorized · charge pending") or `charged` ("Charged on").
            `charged_at` is the date shown after that label.'
        charged_at:
          type: string
          description: Date shown after the payment label ("Charged on" or "Authorized
            on"), display string.
        amount_formatted:
          type: string
          description: Amount, display string such as €188.65.
      description: Payment line of booking confirmation, flight ticketing and exchange
        emails.
    BookingConfirmationEmailContent:
      type: object
      properties:
        trip_reference:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        items:
          type: array
          items:
            $ref: "#/components/schemas/EmailBookingItem"
          description: One entry per product this email covers.
        travelers:
          type: array
          items:
            $ref: "#/components/schemas/EmailPassenger"
          description: Travellers. Personal data.
        charges:
          $ref: "#/components/schemas/EmailChargesBreakdown"
        payment:
          $ref: "#/components/schemas/EmailPayment"
        payment_notice:
          type: string
          description: Payment notice. Not sent today.
      description: What the default booking confirmation email shows at authorization,
        or after capture for ground and car items. Values are display strings as
        the email shows them. Payment is the authorized amount before capture
        and the captured amount afterwards. Charges are not sent today.
    BookingConfirmationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - booking-confirmation
        content:
          $ref: "#/components/schemas/BookingConfirmationEmailContent"
      required:
        - subject
        - template
        - content
      description: Booking confirmation at authorization, or for ground/car after
        capture. This email attaches no calendar.
    BookingProcessingData:
      type: object
      properties:
        manage_booking_url:
          $ref: "#/components/schemas/EmailManageBookingURL"
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/BookingConfirmationCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                booking-confirmation: "#/components/schemas/BookingConfirmationCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      required:
        - customer_emails
      description: Payment authorized; the booking is being confirmed with suppliers.
        Carries the booking confirmation email and its manage-booking link.
    CompletedBookingItem:
      type: object
      properties:
        item_id:
          type: string
          description: The trip item id.
          example: prod-flight-1
        kind:
          type: string
          description: '"flight", "hotel", "car" or "ground".'
          example: flight
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: "The booked item’s handle: `booked_item_id` on get_booking, and
            what servicing takes. Omitted when the platform cannot name the
            item."
          example: itm_aaaabbbbccccdddd
        supplier_references:
          type: array
          items:
            $ref: "#/components/schemas/SupplierReference"
          description: The confirmations the supplier itself issued for this item; `[]`
            when none is known. The Jinko reference is the event-level
            `booking_ref`.
      required:
        - item_id
        - kind
        - supplier_references
      description: "One booked item of a completed booking, with what a partner needs
        to tell the traveller without calling get_booking: its handle and the
        supplier’s own confirmations."
    EmailAirlineLocator:
      type: object
      properties:
        airline_name:
          type: string
          description: Carrier name, IATA code, or Airline when unknown.
        locator:
          type: string
          description: That carrier’s record locator.
      description: One carrier’s record locator on a codeshare or interline booking.
    EmailTicketingFlightSegment:
      type: object
      properties:
        departure_city_name:
          type: string
          description: Departure city, shown in the layover row.
        departure_airport_name:
          type: string
          description: Departure airport name.
        departure_iata:
          type: string
          description: Departure airport IATA code.
        departure_time:
          type: string
          description: Departure local time, display string.
        arrival_airport_name:
          type: string
          description: Arrival airport name.
        arrival_iata:
          type: string
          description: Arrival airport IATA code.
        arrival_time:
          type: string
          description: Arrival local time, display string.
        duration_formatted:
          type: string
          description: Segment duration, such as 2h 15m.
        flight_number:
          type: string
          description: Marketing flight number.
        aircraft:
          type: string
          description: Aircraft type.
        airline_name:
          type: string
          description: Marketing airline name.
        airline_logo_url:
          type: string
          format: uri
          description: Marketing airline logo URL.
        layover_before:
          type: string
          description: Layover before this segment; omitted on the first.
        operating_airline_name:
          type: string
          description: Operating carrier of a codeshare segment; omitted when the
            marketing carrier flies it.
      description: One flown segment on the ticketing confirmation, including the
        operating carrier.
    EmailTicketingFlight:
      type: object
      properties:
        label:
          type: string
          description: "Leg heading: Outbound, Return, or Leg N of M."
        departure_date:
          type: string
          description: Leg departure date, display string.
        cabin_class:
          type: string
          description: Cabin class label, such as Economy.
        segments:
          type: array
          items:
            $ref: "#/components/schemas/EmailTicketingFlightSegment"
          description: Segments in flown order.
      description: One leg as the flight ticketing confirmation shows it.
    EmailFlightFareConditions:
      type: object
      properties:
        refund_policy:
          type: string
          description: Refund policy sentence.
        change_policy:
          type: string
          description: Change policy sentence.
        carry_on_baggage:
          type: string
          description: Carry-on allowance.
        checked_baggage:
          type: string
          description: Checked baggage allowance.
      description: Fare conditions shown by flight ticketing and exchange emails.
    EmailTicketedPassenger:
      type: object
      properties:
        first_name:
          type: string
          description: First name. Personal data.
        last_name:
          type: string
          description: Last name. Personal data.
        type:
          type: string
          description: Adult, Child or Infant.
        date_of_birth:
          type: string
          description: Date of birth as stored. Personal data.
        ticket_number:
          type: string
          description: This passenger’s e-ticket number. Personal data.
      description: A passenger on the flight ticketing confirmation. Personal data.
    FlightTicketingConfirmationEmailContent:
      type: object
      properties:
        booked_seats:
          type: array
          items:
            $ref: "#/components/schemas/EmailBookedSeat"
          description: Seat outcomes over all flight items.
        booked_bags:
          type: array
          items:
            $ref: "#/components/schemas/EmailBookedBag"
          description: Bag outcomes over all flight items.
        pnr:
          type: string
          description: Jinko booking reference, not the airline PNR.
        destination_city_name:
          type: string
          description: Destination of the first leg, as in the headline.
        airline_pnr:
          type: string
          description: Airline record locator; shown when airline_locators is absent.
        airline_locators:
          type: array
          items:
            $ref: "#/components/schemas/EmailAirlineLocator"
          description: Per-carrier locators on a codeshare or interline booking.
        legs:
          type: array
          items:
            $ref: "#/components/schemas/EmailTicketingFlight"
          description: Legs in flown order.
        fare_conditions:
          $ref: "#/components/schemas/EmailFlightFareConditions"
        passengers:
          type: array
          items:
            $ref: "#/components/schemas/EmailTicketedPassenger"
          description: Passengers with their ticket numbers. Personal data.
        payment:
          $ref: "#/components/schemas/EmailPayment"
        charges:
          $ref: "#/components/schemas/EmailChargesBreakdown"
      description: "What the default flight ticketing confirmation shows: the first
        flight item, with captured payment and fare conditions. Values are
        display strings as the email shows them. Charges are not sent today."
    FlightTicketingConfirmationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - flight-ticketing-confirmation
        content:
          $ref: "#/components/schemas/FlightTicketingConfirmationEmailContent"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      required:
        - subject
        - template
        - content
      description: Flight confirmation with e-tickets issued. Calendar contains the
        attached .ics files, omitted when none are attached or there is no
        recipient.
    HotelBookingConfirmationEmailContent:
      type: object
      properties:
        pnr:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        supplier_booking_id:
          type: string
          description: Provider confirmation number.
        hotel:
          $ref: "#/components/schemas/EmailHotel"
        stay:
          $ref: "#/components/schemas/EmailHotelStay"
        room:
          $ref: "#/components/schemas/EmailHotelRoom"
        guests:
          type: array
          items:
            $ref: "#/components/schemas/EmailGuest"
          description: Guests. Personal data.
        cancellation_tiers:
          type: array
          items:
            $ref: "#/components/schemas/EmailCancellationTier"
          description: Cancellation timeline.
        cancellation_text:
          type: string
          description: Cancellation summary, shown when there are no tiers.
        policies:
          type: array
          items:
            $ref: "#/components/schemas/EmailHotelPolicy"
          description: Policy rows, including Total paid and Payment.
      description: "What the default hotel booking confirmation shows: the first hotel
        item, its property, stay and room. Values are display strings as the
        email shows them."
    HotelBookingConfirmationCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - hotel-booking-confirmation
        content:
          $ref: "#/components/schemas/HotelBookingConfirmationEmailContent"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      required:
        - subject
        - template
        - content
      description: Hotel stay confirmation. Calendar contains the attached .ics files,
        omitted when none are attached or there is no recipient.
    BookingCompletedData:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/CompletedBookingItem"
          description: Every booked item, each with its `booked_item_id` and
            `supplier_references`. Absent on events sent before contract 0.75.0.
        manage_booking_url:
          $ref: "#/components/schemas/EmailManageBookingURL"
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/FlightTicketingConfirmationCustomerEmail"
              - $ref: "#/components/schemas/HotelBookingConfirmationCustomerEmail"
              - $ref: "#/components/schemas/BookingConfirmationCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                flight-ticketing-confirmation: "#/components/schemas/FlightTicketingConfirmationCustomerEmail"
                hotel-booking-confirmation: "#/components/schemas/HotelBookingConfirmationCustomerEmail"
                booking-confirmation: "#/components/schemas/BookingConfirmationCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      description: "The booked items with their supplier references, and the
        post-capture emails in sending order: flight, hotel, then one booking
        confirmation for ground and one for car, plus their manage-booking
        link."
    FlightExchangeEmailContent:
      type: object
      properties:
        jinko_ref:
          type: string
          description: Original booking’s Jinko reference, JNK-XXXXXX.
        pnr:
          type: string
          description: Fallback for jinko_ref, a deprecated duplicate.
        previous_pnr:
          type: string
          description: Fallback for previous_airline_pnr, a duplicate.
        airline_pnr:
          type: string
          description: Airline locator after the exchange.
        previous_airline_pnr:
          type: string
          description: Airline locator before the exchange; shown only when it differs
            from airline_pnr.
        ticket_number:
          type: string
          description: E-ticket number; shown only when revalidated. Personal data.
        charges:
          $ref: "#/components/schemas/EmailChargesBreakdown"
        payment:
          $ref: "#/components/schemas/EmailPayment"
        legs:
          type: array
          items:
            $ref: "#/components/schemas/EmailFlight"
          description: New itinerary legs.
        outbound_flight:
          $ref: "#/components/schemas/EmailFlightHeadline"
        fare_conditions:
          $ref: "#/components/schemas/EmailFlightFareConditions"
        passengers:
          type: array
          items:
            $ref: "#/components/schemas/EmailPassenger"
          description: Passengers. Personal data.
        document_revalidated:
          type: boolean
          description: "No new document: the held e-ticket was revalidated and keeps its
            number."
        document_unobserved:
          type: boolean
          description: Reissued, with the new e-ticket number not known yet;
            servicing.ticket_issued may follow.
      required:
        - document_revalidated
        - document_unobserved
      description: "What the default flight exchange email shows: new itinerary,
        first-leg headline and new fare conditions. Values are display strings
        as the email shows them; booleans are always sent. Charges are the
        quoted fare difference, fee and total, before settlement. Payment is not
        sent today."
    FlightExchangeCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - flight-exchange
        content:
          $ref: "#/components/schemas/FlightExchangeEmailContent"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      required:
        - subject
        - template
        - content
      description: Flight exchange confirmation. Calendar contains the attached .ics
        files, omitted when none are attached or there is no recipient.
    EmailChangeEntry:
      type: object
      properties:
        label:
          type: string
          description: "What changed: Vehicle, Pick-up, Drop-off."
        before:
          type: string
          description: Value before, display string.
        after:
          type: string
          description: Value after, display string.
      description: One before/after row of a car exchange.
    EmailCardPayment:
      type: object
      properties:
        card_brand:
          type: string
          description: Card brand.
        last_four:
          type: string
          description: Card last four. Sensitive payment data.
      description: Card line of a car exchange email.
    CarExchangeEmailContent:
      type: object
      properties:
        pnr:
          type: string
          description: Original Jinko booking reference, unchanged.
        confirmation_code:
          type: string
          description: Rental supplier’s reservation number, unchanged.
        exchanged_at:
          type: string
          description: Exchange date, display string.
        car:
          $ref: "#/components/schemas/EmailCar"
        changes:
          type: array
          items:
            $ref: "#/components/schemas/EmailChangeEntry"
          description: What changed; may be absent.
        drivers:
          type: array
          items:
            $ref: "#/components/schemas/EmailGuest"
          description: Drivers. Personal data.
        settlement_charged:
          type: boolean
          description: The difference was collected.
        settlement_refunded:
          type: boolean
          description: The difference was refunded.
        refund_pending_review:
          type: boolean
          description: Changed, with the refund of the difference awaiting human review;
            no amounts.
        delta_formatted:
          type: string
          description: Absolute price difference; the flag gives the direction.
        new_total_formatted:
          type: string
          description: Rental total after the exchange.
        payment:
          $ref: "#/components/schemas/EmailCardPayment"
      required:
        - settlement_charged
        - settlement_refunded
        - refund_pending_review
      description: What the default car exchange email shows for the rental as it now
        stands. Values are display strings as the email shows them; booleans are
        always sent. When all three settlement flags are false there is no
        difference to settle. Pending review omits amounts and payment; no
        difference omits delta_formatted. Payment is not sent today.
    CarExchangeCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - car-exchange
        content:
          $ref: "#/components/schemas/CarExchangeEmailContent"
      required:
        - subject
        - template
        - content
      description: Car rental change confirmation. This email attaches no calendar.
    ServicingExchangeConfirmedData:
      type: object
      properties:
        operation:
          type: string
          description: Servicing operation handle (svc_…), sent only when the operation
            has one. Other exchange identifiers are never sent in this field.
        booked_item_id:
          type: string
          description: The booked item serviced — `booked_item_id` on get_booking; omitted
            when unknown.
        item:
          type: integer
          description: "Deprecated: use `booked_item_id` instead. The booked item as an
            integer."
          deprecated: true
        booking_ref:
          type: string
          description: Original booking’s Jinko reference, JNK-XXXXXX.
        operation_kind:
          type: string
          enum:
            - exchange
          description: "The servicing operation: exchange."
        manage_booking_url:
          $ref: "#/components/schemas/EmailManageBookingURL"
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/FlightExchangeCustomerEmail"
              - $ref: "#/components/schemas/CarExchangeCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                flight-exchange: "#/components/schemas/FlightExchangeCustomerEmail"
                car-exchange: "#/components/schemas/CarExchangeCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      required:
        - operation_kind
        - customer_emails
      description: The supplier confirmed an exchange of one booked item. Carries the
        flight exchange or car exchange email. The manage-booking link is
        currently sent only for car exchanges.
    FlightExchangeTicketNumberEmailContent:
      type: object
      properties:
        pnr:
          type: string
          description: Original booking’s Jinko reference, JNK-XXXXXX.
        airline_pnr:
          type: string
          description: Airline locator after the exchange.
        customer_name:
          type: string
          description: "Greeting name: the contact’s first name. Personal data."
        ticket_numbers:
          type: array
          items:
            type: string
          description: Reissued e-ticket numbers. Personal data.
      description: What the ticket-number follow-up email shows after a flight
        exchange. Values are display strings as the email shows them.
    FlightExchangeTicketNumberCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - flight-exchange-ticket-number
        content:
          $ref: "#/components/schemas/FlightExchangeTicketNumberEmailContent"
      required:
        - subject
        - template
        - content
      description: New e-ticket number of an exchanged flight. This email attaches no
        calendar.
    ServicingTicketIssuedData:
      type: object
      properties:
        operation:
          type: string
          description: Servicing operation handle (svc_…), sent only when the operation
            has one. Other exchange identifiers are never sent in this field.
        booked_item_id:
          type: string
          description: The booked item serviced — `booked_item_id` on get_booking; omitted
            when unknown.
        item:
          type: integer
          description: "Deprecated: use `booked_item_id` instead. The booked item as an
            integer."
          deprecated: true
        booking_ref:
          type: string
          description: Original booking’s Jinko reference, JNK-XXXXXX.
        operation_kind:
          type: string
          enum:
            - exchange
          description: "The servicing operation: exchange."
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/FlightExchangeTicketNumberCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                flight-exchange-ticket-number: "#/components/schemas/FlightExchangeTicketNumberCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      required:
        - operation_kind
        - customer_emails
      description: The reissued e-ticket number is known, following a flight exchange
        with document_unobserved true. Carries the ticket-number follow-up
        email.
    EmailLegacyFlight:
      type: object
      properties:
        origin_name:
          type: string
          description: Origin city name.
        destination_name:
          type: string
          description: Destination city name.
        departure_date:
          type: string
          description: Departure date, display string.
        departure_time:
          type: string
          description: Departure time, 24-hour display string.
        arrival_time:
          type: string
          description: Arrival time, 24-hour display string.
        duration_formatted:
          type: string
          description: Duration, or 0h 00m when unknown.
        airline_name:
          type: string
          description: Airline name.
        flight_number:
          type: string
          description: First segment’s flight number.
        cabin_class:
          type: string
          description: Cabin class label.
      description: Single-journey card of an exchange or refund failure email.
    EmailNamedPassenger:
      type: object
      properties:
        first_name:
          type: string
          description: First name. Personal data.
        last_name:
          type: string
          description: Last name. Personal data.
        type:
          type: string
          description: Adult, Child or Infant.
      description: A traveller on an exchange or refund failure email. Personal data.
    ExchangeFailedEmailContent:
      type: object
      properties:
        original_pnr:
          type: string
          description: Booking reference the email says is unchanged.
        original_booking_ref:
          type: string
          description: Booking reference to quote to support.
        original_outbound:
          $ref: "#/components/schemas/EmailLegacyFlight"
        original_inbound:
          $ref: "#/components/schemas/EmailLegacyFlight"
        passengers:
          type: array
          items:
            $ref: "#/components/schemas/EmailNamedPassenger"
          description: Passengers or drivers. Personal data.
        exchange_noun:
          type: string
          description: "Operation name: Flight Exchange or Car Rental Change."
        change_target_phrase:
          type: string
          description: "What the traveller wanted to change: these flights or this rental."
        traveler_label:
          type: string
          description: "People list heading: Passengers or Drivers."
        item_summary:
          type: string
          description: One-line recap of the unchanged booking for car exchanges.
      description: What the exchange failure email shows, including current
        outbound/return flights when applicable and resolved flight or rental
        nouns. Values are display strings as the email shows them.
    ExchangeFailedCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - exchange-failed
        content:
          $ref: "#/components/schemas/ExchangeFailedEmailContent"
      required:
        - subject
        - template
        - content
      description: Flight exchange or car rental change could not be completed. This
        email attaches no calendar.
    RefundFailedEmailContent:
      type: object
      properties:
        product_label:
          type: string
          description: "Product noun: flight, hotel or booking; defaults to booking."
        booking_reference:
          type: string
          description: Jinko booking reference, JNK-XXXXXX.
        provider_reference:
          type: string
          description: Airline PNR or hotel confirmation code.
        outbound:
          $ref: "#/components/schemas/EmailLegacyFlight"
        inbound:
          $ref: "#/components/schemas/EmailLegacyFlight"
        hotel_name:
          type: string
          description: Hotel name for hotel refunds.
        hotel_address:
          type: string
          description: Hotel address for hotel refunds.
        stay_label:
          type: string
          description: Stay dates as stored, such as 2026-06-01 – 2026-06-04.
        room_label:
          type: string
          description: Room name for hotel refunds.
        refund_amount_formatted:
          type: string
          description: Expected refund; the email says support will confirm it.
        reason:
          type: string
          description: Explanation. Not sent today.
        travelers:
          type: array
          items:
            $ref: "#/components/schemas/EmailNamedPassenger"
          description: Travellers. Personal data.
      description: What the refund failure email shows, including outbound/return
        flights for flight refunds or the hotel stay for hotel refunds. Values
        are display strings as the email shows them.
    RefundFailedCustomerEmail:
      type: object
      properties:
        to:
          type: string
          format: email
          description: Recipient contact address; omitted when there is none. Personal data.
        subject:
          type: string
          description: Subject line built from the same email data.
        template:
          type: string
          enum:
            - refund-failed
        content:
          $ref: "#/components/schemas/RefundFailedEmailContent"
      required:
        - subject
        - template
        - content
      description: Automated refund or void could not be completed. This email
        attaches no calendar.
    ServicingFailedData:
      type: object
      properties:
        operation:
          type: string
          description: Servicing operation handle (svc_…), sent only when the operation
            has one. Other exchange identifiers are never sent in this field.
        booked_item_id:
          type: string
          description: The booked item serviced — `booked_item_id` on get_booking; omitted
            when unknown.
        item:
          type: integer
          description: "Deprecated: use `booked_item_id` instead. The booked item as an
            integer."
          deprecated: true
        booking_ref:
          type: string
          description: Original booking’s Jinko reference, JNK-XXXXXX.
        operation_kind:
          type: string
          enum:
            - exchange
            - refund
            - void
          description: The operation that failed. The refund failure email covers refunds
            and voids.
        customer_emails:
          type: array
          items:
            oneOf:
              - $ref: "#/components/schemas/ExchangeFailedCustomerEmail"
              - $ref: "#/components/schemas/RefundFailedCustomerEmail"
            discriminator:
              propertyName: template
              mapping:
                exchange-failed: "#/components/schemas/ExchangeFailedCustomerEmail"
                refund-failed: "#/components/schemas/RefundFailedCustomerEmail"
          minItems: 1
          description: One entry per email Jinko sends or would send at this moment, in
            sending order, even if email delivery is disabled. Template selects
            the content shape.
      required:
        - operation_kind
        - customer_emails
      description: An exchange, refund or void could not be completed. Carries its
        failure email. No operation handle is sent today.
    WebhookEventPayload:
      type: object
      properties:
        event:
          $ref: "#/components/schemas/WebhookEvent"
        booking_ref:
          type: string
          description: Empty string when the event concerns no single booking.
          example: JNK-A0AUR2
        status:
          type: string
          description: "Deprecated: branch on `event`, which already names the outcome.
            Resulting booking state: `processing` for booking.processing,
            `confirmed` for booking.completed, `failed` for booking.failed,
            `partial` for booking.partial, `servicing.completed` for
            servicing.completed, `servicing.exchange_confirmed` for
            servicing.exchange_confirmed, `servicing.ticket_issued` for
            servicing.ticket_issued, `servicing.failed` for servicing.failed."
          example: confirmed
          deprecated: true
        occurred_at:
          type: string
          description: When the event happened, RFC 3339 UTC — NOT when it was delivered.
            A retry or a replay carries the original instant.
          example: "2026-09-02T08:55:34Z"
        event_id:
          type: string
          description: "Unique per occurrence of an event: a servicing event, which can
            happen more than once on one booking, has a new one each time (each
            cancellation has its own). Deliveries are deduplicated on it, and a
            retry or a replay repeats it — key your own idempotency off this.
            Treat it as an opaque string: its format is not part of the
            contract."
          example: evt_2097152_booking.partial
        livemode:
          type: boolean
          description: False when the event came from a sandbox booking.
          example: true
        data:
          anyOf:
            - $ref: "#/components/schemas/PartialBookingData"
            - $ref: "#/components/schemas/ServicingCompletedData"
            - $ref: "#/components/schemas/BookingFailedData"
            - $ref: "#/components/schemas/BookingProcessingData"
            - $ref: "#/components/schemas/BookingCompletedData"
            - $ref: "#/components/schemas/ServicingExchangeConfirmedData"
            - $ref: "#/components/schemas/ServicingTicketIssuedData"
            - $ref: "#/components/schemas/ServicingFailedData"
      required:
        - event
        - booking_ref
        - status
        - occurred_at
        - event_id
        - livemode
      description: "The signed body POSTed to a registered webhook URL, also available
        in the delivery log until its payload is purged. Verify the signature
        against the secret returned once at registration before trusting a
        delivery. `data` is event-specific: `PartialBookingData` on
        `booking.partial`, `ServicingCompletedData` on `servicing.completed`,
        `BookingFailedData` on `booking.failed`, `BookingProcessingData` on
        `booking.processing`, `BookingCompletedData` on `booking.completed`,
        `ServicingExchangeConfirmedData` on `servicing.exchange_confirmed`,
        `ServicingTicketIssuedData` on `servicing.ticket_issued`,
        `ServicingFailedData` on `servicing.failed`. `manage_booking_url` and
        `customer_emails[]` hold traveller personal data and mirror what Jinko’s
        email shows. Email content uses display strings; empty strings, nulls,
        empty lists and empty objects are omitted from new fields. Integers and
        booleans are always sent. Existing data fields retain their original
        behaviour, including nulls."
    HealthResponse:
      type: object
      properties:
        status:
          type: string
          enum:
            - ok
        service:
          type: string
          enum:
            - jinko-api
        version:
          type: string
          example: 0.1.0
      required:
        - status
        - service
        - version
    FlightPriceAdviceAmount:
      type: object
      properties:
        value:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: Positive integer in currency minor units.
          example: 32000
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          example: USD
        decimal_places:
          type: integer
          minimum: 0
          example: 2
      required:
        - value
        - currency
        - decimal_places
      additionalProperties: false
      description: One adult total fare for the supplied trip, including tax and
        excluding optional paid extras. Value 32000, USD, decimal_places 2 means
        USD 320.00.
    FlightPriceAdviceContext:
      type: object
      properties:
        origin:
          type: string
          pattern: ^[A-Z]{3}$
          example: NYC
        destination:
          type: string
          pattern: ^[A-Z]{3}$
          example: LAX
        departure_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: "2026-10-20"
        trip_type:
          type: string
          enum: &a6
            - oneway
            - roundtrip
        return_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: The requested return date. Present on round-trip responses, absent
            on one-way responses.
          example: "2026-10-27"
        stops:
          type: number
          description: Actual number of flight connections, or null when the request
            omitted stops.
          nullable: true
          anyOf:
            - type: number
              enum:
                - 0
                - 1
                - 2
            - not:
                type: number
        cabin_class:
          type: string
          enum: &a7
            - economy
            - premium_economy
            - business
            - first
        current_price:
          $ref: "#/components/schemas/FlightPriceAdviceAmount"
        price_basis:
          type: string
          enum:
            - per_adult_total_including_tax
        evaluated_at:
          type: string
          format: date-time
        apex_days:
          type: integer
          minimum: 0
          exclusiveMinimum: true
      required:
        - origin
        - destination
        - departure_date
        - trip_type
        - stops
        - cabin_class
        - current_price
        - price_basis
        - evaluated_at
        - apex_days
      additionalProperties: false
    FlightPriceAdviceExpectedFareRecommendationBasis:
      type: object
      properties:
        policy:
          type: string
          enum:
            - expected_fare
        price_label:
          type: string
          enum:
            - low
            - typical
            - high
        selected_horizon_days:
          anyOf:
            - type: number
              enum:
                - 1
            - type: number
              enum:
                - 3
        wait_direction:
          type: string
          enum:
            - increase
            - decrease
            - unchanged
      required:
        - policy
        - price_label
        - selected_horizon_days
        - wait_direction
      additionalProperties: false
    FlightPriceAdviceModalDirectionRecommendationBasis:
      type: object
      properties:
        policy:
          type: string
          enum:
            - modal_direction
        price_label:
          type: string
          enum:
            - low
            - typical
            - high
        selected_horizon_days:
          type: number
          nullable: true
          not: &a2
            type: number
        wait_direction:
          type: string
          enum:
            - increase
            - decrease
      required:
        - policy
        - price_label
        - selected_horizon_days
        - wait_direction
      additionalProperties: false
    FlightPriceAdvicePriceAssessmentRecommendationBasis:
      type: object
      properties:
        policy:
          type: string
          enum:
            - price_assessment
        price_label:
          type: string
          enum:
            - low
        selected_horizon_days:
          type: number
          nullable: true
          not: *a2
        wait_direction:
          type: number
          nullable: true
          not: *a2
      required:
        - policy
        - price_label
        - selected_horizon_days
        - wait_direction
      additionalProperties: false
    FlightPriceAdviceResponse:
      type: object
      properties:
        schema_version:
          type: string
          enum:
            - "3.2"
        status:
          type: string
          enum:
            - available
            - partial
            - unavailable
            - not_ready
        reason:
          type: string
          nullable: true
          anyOf:
            - type: string
              enum:
                - statistics_not_ready
                - future_statistics
                - stale_statistics
                - unsupported_currency
                - unsupported_trip_type
                - stops_unknown
                - unsupported_stops
                - route_not_covered
                - insufficient_data
                - horizon_not_supported
                - unsafe_projected_amount
                - request_cancelled
                - partial_statistics
                - statistics_unavailable
            - not:
                type: string
        summary:
          type: string
          minLength: 1
        context:
          $ref: "#/components/schemas/FlightPriceAdviceContext"
        price_assessment:
          oneOf:
            - type: object
              properties:
                status:
                  type: string
                  enum:
                    - available
                reason_code:
                  type: number
                  nullable: true
                  not: *a2
                label:
                  type: string
                  enum:
                    - low
                    - typical
                    - high
                typical_price:
                  $ref: "#/components/schemas/FlightPriceAdviceAmount"
                typical_range:
                  type: object
                  properties:
                    low:
                      $ref: "#/components/schemas/FlightPriceAdviceAmount"
                    high:
                      $ref: "#/components/schemas/FlightPriceAdviceAmount"
                  required:
                    - low
                    - high
                  additionalProperties: false
                percentile:
                  type: number
                  minimum: 0
                  maximum: 100
                difference_pct:
                  type: number
                comparison_basis:
                  type: string
                  enum:
                    - historical_comparable_low_fares
                evidence:
                  type: object
                  properties:
                    artifact_id:
                      type: string
                      pattern: ^price-advice-v[1-9][0-9]*-[a-f0-9]{64}$
                    fit_window:
                      type: object
                      properties:
                        start:
                          type: string
                          format: date-time
                        end_exclusive:
                          type: string
                          format: date-time
                      required:
                        - start
                        - end_exclusive
                      additionalProperties: false
                    source_price_unit:
                      type: string
                      enum:
                        - amd_totalpricenuc_millicents
                    currency_mapping:
                      type: string
                      enum:
                        - gateway_platform_usd_millicents_to_usd_minor_units_divide_by_10
                    apex_band:
                      type: string
                      enum:
                        - 0-2
                        - 3-6
                        - 7-13
                        - 14-20
                        - 21-29
                        - 30-59
                        - 60-89
                        - 90-179
                        - ">=180"
                    support:
                      type: object
                      properties:
                        daily_units:
                          type: integer
                          minimum: 0
                          exclusiveMinimum: true
                        observation_days:
                          type: integer
                          minimum: 0
                          exclusiveMinimum: true
                        departure_dates:
                          type: integer
                          minimum: 0
                          exclusiveMinimum: true
                        flight_identities:
                          type: integer
                          minimum: 0
                          exclusiveMinimum: true
                      required:
                        - daily_units
                        - observation_days
                        - departure_dates
                        - flight_identities
                      additionalProperties: false
                    stay_band:
                      type: string
                      minLength: 1
                      description: The band of stay lengths (days from departure_date to return_date)
                        whose comparable round-trip fares were used. Present on
                        round-trip responses, absent on one-way responses.
                  required:
                    - artifact_id
                    - fit_window
                    - source_price_unit
                    - currency_mapping
                    - apex_band
                    - support
                  additionalProperties: false
              required:
                - status
                - reason_code
                - label
                - typical_price
                - typical_range
                - percentile
                - difference_pct
                - comparison_basis
                - evidence
              additionalProperties: false
            - type: object
              properties:
                status:
                  type: string
                  enum:
                    - unavailable
                reason_code:
                  type: string
                  enum: &a4
                    - statistics_not_ready
                    - future_statistics
                    - stale_statistics
                    - unsupported_currency
                    - unsupported_trip_type
                    - stops_unknown
                    - unsupported_stops
                    - route_not_covered
                    - insufficient_data
                    - horizon_not_supported
                    - unsafe_projected_amount
                    - request_cancelled
                    - partial_statistics
                    - statistics_unavailable
                label:
                  type: number
                  nullable: true
                  not: *a2
                typical_price:
                  type: number
                  nullable: true
                  not: *a2
                typical_range:
                  type: number
                  nullable: true
                  not: *a2
                percentile:
                  type: number
                  nullable: true
                  not: *a2
                difference_pct:
                  type: number
                  nullable: true
                  not: *a2
                comparison_basis:
                  type: string
                  enum:
                    - historical_comparable_low_fares
                evidence:
                  type: number
                  nullable: true
                  not: *a2
              required:
                - status
                - reason_code
                - label
                - typical_price
                - typical_range
                - percentile
                - difference_pct
                - comparison_basis
                - evidence
              additionalProperties: false
        wait_assessment:
          anyOf:
            - type: object
              properties:
                status:
                  type: string
                  enum:
                    - available
                reason_code:
                  type: number
                  nullable: true
                  not: *a2
                horizons:
                  type: array
                  items:
                    anyOf:
                      - type: object
                        properties:
                          horizon_days:
                            type: number
                            enum:
                              - 1
                          status:
                            type: string
                            enum:
                              - available
                          reason_code:
                            type: number
                            nullable: true
                            not: *a2
                          direction:
                            type: string
                            enum: &a3
                              - increase
                              - decrease
                              - unchanged
                              - mixed
                          forecasted_price:
                            $ref: "#/components/schemas/FlightPriceAdviceAmount"
                          probabilities:
                            type: object
                            properties:
                              increase:
                                type: number
                                minimum: 0
                                maximum: 1
                              decrease:
                                type: number
                                minimum: 0
                                maximum: 1
                              unchanged:
                                type: number
                                minimum: 0
                                maximum: 1
                            required:
                              - increase
                              - decrease
                              - unchanged
                            additionalProperties: false
                        required:
                          - horizon_days
                          - status
                          - reason_code
                          - direction
                          - forecasted_price
                          - probabilities
                        additionalProperties: false
                      - type: object
                        properties:
                          horizon_days:
                            type: number
                            enum:
                              - 3
                          status:
                            type: string
                            enum:
                              - available
                          reason_code:
                            type: number
                            nullable: true
                            not: *a2
                          direction:
                            type: string
                            enum: &a5
                              - increase
                              - decrease
                              - unchanged
                              - mixed
                          forecasted_price:
                            $ref: "#/components/schemas/FlightPriceAdviceAmount"
                          probabilities:
                            type: object
                            properties:
                              increase:
                                type: number
                                minimum: 0
                                maximum: 1
                              decrease:
                                type: number
                                minimum: 0
                                maximum: 1
                              unchanged:
                                type: number
                                minimum: 0
                                maximum: 1
                            required:
                              - increase
                              - decrease
                              - unchanged
                            additionalProperties: false
                        required:
                          - horizon_days
                          - status
                          - reason_code
                          - direction
                          - forecasted_price
                          - probabilities
                        additionalProperties: false
                  minItems: 2
                  maxItems: 2
              required:
                - status
                - reason_code
                - horizons
              additionalProperties: false
            - type: object
              properties:
                status:
                  type: string
                  enum:
                    - partial
                reason_code:
                  type: string
                  enum:
                    - partial_statistics
                horizons:
                  anyOf:
                    - type: array
                      items:
                        anyOf:
                          - type: object
                            properties:
                              horizon_days:
                                type: number
                                enum:
                                  - 1
                              status:
                                type: string
                                enum:
                                  - available
                              reason_code:
                                type: number
                                nullable: true
                                not: *a2
                              direction:
                                type: string
                                enum: *a3
                              forecasted_price:
                                $ref: "#/components/schemas/FlightPriceAdviceAmount"
                              probabilities:
                                type: object
                                properties:
                                  increase:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                  decrease:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                  unchanged:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                required:
                                  - increase
                                  - decrease
                                  - unchanged
                                additionalProperties: false
                            required:
                              - horizon_days
                              - status
                              - reason_code
                              - direction
                              - forecasted_price
                              - probabilities
                            additionalProperties: false
                          - type: object
                            properties:
                              horizon_days:
                                type: number
                                enum:
                                  - 3
                              status:
                                type: string
                                enum:
                                  - unavailable
                              reason_code:
                                type: string
                                enum: *a4
                              direction:
                                type: number
                                nullable: true
                                not: *a2
                              forecasted_price:
                                type: number
                                nullable: true
                                not: *a2
                              probabilities:
                                type: object
                                properties:
                                  increase:
                                    type: number
                                    nullable: true
                                    not: *a2
                                  decrease:
                                    type: number
                                    nullable: true
                                    not: *a2
                                  unchanged:
                                    type: number
                                    nullable: true
                                    not: *a2
                                required:
                                  - increase
                                  - decrease
                                  - unchanged
                                additionalProperties: false
                            required:
                              - horizon_days
                              - status
                              - reason_code
                              - direction
                              - forecasted_price
                              - probabilities
                            additionalProperties: false
                      minItems: 2
                      maxItems: 2
                    - type: array
                      items:
                        anyOf:
                          - type: object
                            properties:
                              horizon_days:
                                type: number
                                enum:
                                  - 1
                              status:
                                type: string
                                enum:
                                  - unavailable
                              reason_code:
                                type: string
                                enum: *a4
                              direction:
                                type: number
                                nullable: true
                                not: *a2
                              forecasted_price:
                                type: number
                                nullable: true
                                not: *a2
                              probabilities:
                                type: object
                                properties:
                                  increase:
                                    type: number
                                    nullable: true
                                    not: *a2
                                  decrease:
                                    type: number
                                    nullable: true
                                    not: *a2
                                  unchanged:
                                    type: number
                                    nullable: true
                                    not: *a2
                                required:
                                  - increase
                                  - decrease
                                  - unchanged
                                additionalProperties: false
                            required:
                              - horizon_days
                              - status
                              - reason_code
                              - direction
                              - forecasted_price
                              - probabilities
                            additionalProperties: false
                          - type: object
                            properties:
                              horizon_days:
                                type: number
                                enum:
                                  - 3
                              status:
                                type: string
                                enum:
                                  - available
                              reason_code:
                                type: number
                                nullable: true
                                not: *a2
                              direction:
                                type: string
                                enum: *a5
                              forecasted_price:
                                $ref: "#/components/schemas/FlightPriceAdviceAmount"
                              probabilities:
                                type: object
                                properties:
                                  increase:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                  decrease:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                  unchanged:
                                    type: number
                                    minimum: 0
                                    maximum: 1
                                required:
                                  - increase
                                  - decrease
                                  - unchanged
                                additionalProperties: false
                            required:
                              - horizon_days
                              - status
                              - reason_code
                              - direction
                              - forecasted_price
                              - probabilities
                            additionalProperties: false
                      minItems: 2
                      maxItems: 2
              required:
                - status
                - reason_code
                - horizons
              additionalProperties: false
            - type: object
              properties:
                status:
                  type: string
                  enum:
                    - unavailable
                reason_code:
                  type: string
                  enum: *a4
                horizons:
                  type: array
                  items:
                    anyOf:
                      - type: object
                        properties:
                          horizon_days:
                            type: number
                            enum:
                              - 1
                          status:
                            type: string
                            enum:
                              - unavailable
                          reason_code:
                            type: string
                            enum: *a4
                          direction:
                            type: number
                            nullable: true
                            not: *a2
                          forecasted_price:
                            type: number
                            nullable: true
                            not: *a2
                          probabilities:
                            type: object
                            properties:
                              increase:
                                type: number
                                nullable: true
                                not: *a2
                              decrease:
                                type: number
                                nullable: true
                                not: *a2
                              unchanged:
                                type: number
                                nullable: true
                                not: *a2
                            required:
                              - increase
                              - decrease
                              - unchanged
                            additionalProperties: false
                        required:
                          - horizon_days
                          - status
                          - reason_code
                          - direction
                          - forecasted_price
                          - probabilities
                        additionalProperties: false
                      - type: object
                        properties:
                          horizon_days:
                            type: number
                            enum:
                              - 3
                          status:
                            type: string
                            enum:
                              - unavailable
                          reason_code:
                            type: string
                            enum: *a4
                          direction:
                            type: number
                            nullable: true
                            not: *a2
                          forecasted_price:
                            type: number
                            nullable: true
                            not: *a2
                          probabilities:
                            type: object
                            properties:
                              increase:
                                type: number
                                nullable: true
                                not: *a2
                              decrease:
                                type: number
                                nullable: true
                                not: *a2
                              unchanged:
                                type: number
                                nullable: true
                                not: *a2
                            required:
                              - increase
                              - decrease
                              - unchanged
                            additionalProperties: false
                        required:
                          - horizon_days
                          - status
                          - reason_code
                          - direction
                          - forecasted_price
                          - probabilities
                        additionalProperties: false
                  minItems: 2
                  maxItems: 2
              required:
                - status
                - reason_code
                - horizons
              additionalProperties: false
        recommendation:
          anyOf:
            - type: object
              properties:
                action:
                  type: string
                  enum:
                    - buy_now
                    - wait
                basis:
                  oneOf:
                    - $ref: "#/components/schemas/FlightPriceAdviceExpectedFareRecommendationBasis"
                    - $ref: "#/components/schemas/FlightPriceAdviceModalDirectionRecommendationBasis"
                    - $ref: "#/components/schemas/FlightPriceAdvicePriceAssessmentRecommendationBasis"
                  discriminator:
                    propertyName: policy
                    mapping:
                      expected_fare: "#/components/schemas/FlightPriceAdviceExpectedFareRecommendatio\
                        nBasis"
                      modal_direction: "#/components/schemas/FlightPriceAdviceModalDirectionRecommend\
                        ationBasis"
                      price_assessment: "#/components/schemas/FlightPriceAdvicePriceAssessmentRecomme\
                        ndationBasis"
                summary:
                  type: string
                  minLength: 1
              required:
                - action
                - basis
                - summary
              additionalProperties: false
            - type: object
              properties:
                action:
                  type: string
                  enum:
                    - no_clear_signal
                basis:
                  type: object
                  nullable: true
                  oneOf:
                    - $ref: "#/components/schemas/FlightPriceAdviceExpectedFareRecommendationBasis"
                    - $ref: "#/components/schemas/FlightPriceAdviceModalDirectionRecommendationBasis"
                    - $ref: "#/components/schemas/FlightPriceAdvicePriceAssessmentRecommendationBasis"
                    - type: number
                      nullable: true
                      not:
                        type: number
                summary:
                  type: string
                  minLength: 1
              required:
                - action
                - basis
                - summary
              additionalProperties: false
        live_quotes_used:
          type: boolean
          enum:
            - false
      required:
        - schema_version
        - status
        - reason
        - summary
        - context
        - price_assessment
        - wait_assessment
        - recommendation
        - live_quotes_used
      additionalProperties: false
      description: Price advice. Results may be available, partial, unavailable, or
        not ready; fixed 1-day and 3-day horizons are always present.
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - INVALID_SEGMENTS_TO_EXCHANGE
                - PARTIAL_EXCHANGE_UNSUPPORTED
                - LEG_ALREADY_DEPARTED
                - DEPARTURE_DATE_IN_PAST
                - LEG_DATES_OUT_OF_ORDER
                - INVALID_EXCHANGE_REQUEST
                - NOT_EXCHANGEABLE
                - CREDENTIAL_FORMAT_INVALID
                - PAYMENT_TYPE_NOT_ENABLED
                - PAYMENT_CREDENTIAL_INVALID
                - TRIP_OWNED_BY_OTHER_PAYMENT
                - IDEMPOTENCY_KEY_REUSED
                - ATTEMPT_IN_PROGRESS
                - ATTEMPT_TERMINAL
                - TEMPORARILY_UNAVAILABLE
                - AUTH_REQUIRED
                - PAYMENT_REQUIRED
                - RATE_LIMITED
                - BAD_REQUEST
                - FORBIDDEN
                - NOT_FOUND
                - CONFLICT
                - GONE
                - QUOTE_PENDING
                - QUOTE_EXPIRED
                - TRIP_EXPIRED
                - TRIP_STATE_CONFLICT
                - OFFER_EXPIRED
                - OFFER_UNAVAILABLE
                - MISSING_CUSTOMER_DETAILS
                - INVALID_PHONE_NUMBER
                - CURRENCY_UNSUPPORTED
                - HOTEL_NAME_LOW_CONFIDENCE
                - DESTINATION_LOW_CONFIDENCE
                - UPSTREAM_REJECTED
                - UPSTREAM_UNAVAILABLE
                - UPSTREAM_TIMEOUT
                - UPSTREAM_ERROR
                - INTERNAL
              description: "What went wrong, as a stable machine-readable code. This is a
                closed set — branch on it rather than on `message`, which is
                prose and may change. New codes arrive in a minor version, so
                treat an unknown one as its HTTP status. A code can also stop
                being emitted: it leaves this set in a minor version, named in
                the changelog, and a branch you wrote for it goes unreached
                rather than wrong."
              example: BAD_REQUEST
            message:
              type: string
              description: 'What went wrong, in prose. These codes always carry the same
                message, and it never includes text from a supplier:
                `RATE_LIMITED` — "Too many requests. Retry after the Retry-After
                delay."; `OFFER_EXPIRED` — "This offer has expired. Search
                again."; `OFFER_UNAVAILABLE` — "This offer is no longer
                available. Search again."; `UPSTREAM_REJECTED` — "The request
                was declined for this offer. Try another offer.";
                `UPSTREAM_UNAVAILABLE` — "The service is temporarily
                unavailable. Retry after the Retry-After delay.";
                `UPSTREAM_TIMEOUT` — "The request timed out before a result was
                available. Retry the request."; `UPSTREAM_ERROR` — "The request
                could not be completed.".'
            doc_url:
              type: string
            field:
              type: string
              description: "On a 400 `BAD_REQUEST` that names one refused input: the path of
                that field in your request, e.g. `selections[1].quantity` for
                the second selection of a `select_ancillaries` call. Absent when
                the refusal names no single field."
              example: selections[1].quantity
          required:
            - code
            - message
      required:
        - error
    FlightPriceAdviceRequest:
      type: object
      properties:
        origin:
          type: string
          pattern: ^[A-Z]{3}$
          example: NYC
        destination:
          type: string
          pattern: ^[A-Z]{3}$
          example: LAX
        departure_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          example: "2026-10-20"
        trip_type:
          type: string
          enum: *a6
        return_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Return date in YYYY-MM-DD format, a real calendar date on or after
            departure_date. Required when trip_type is roundtrip; must be
            omitted when trip_type is oneway.
          example: "2026-10-27"
        stops:
          type: number
          description: "Actual number of flight connections: 0 for nonstop, 1, or 2. Omit
            when unknown. For a round trip, 0 means nonstop on both the outbound
            and the inbound flight; 1 and 2 are not covered for round trips."
          enum:
            - 0
            - 1
            - 2
        cabin_class:
          type: string
          enum: *a7
        current_price:
          $ref: "#/components/schemas/FlightPriceAdviceAmount"
      required:
        - origin
        - destination
        - departure_date
        - trip_type
        - cabin_class
        - current_price
      additionalProperties: false
      description: A flight and its current price. Trip type, the optional actual
        connection count, and cabin are validated as values; a valid request
        does not imply that statistics cover it. A round trip names its
        return_date.
    HotelBed:
      type: object
      properties:
        bed_type:
          type: string
        count:
          type: integer
          minimum: 1
      required:
        - bed_type
        - count
    CancellationStep:
      type: object
      properties:
        cancel_time:
          type: string
          description: Deadline after which this tier applies. RFC 3339 with the
            supplier’s declared UTC offset. Steps whose deadline has no declared
            timezone are omitted from the ladder — the platform never invents an
            offset — so a schedule can be shorter than the supplier’s own. Tiers
            are chronological, earliest first, so the first entry is the
            deadline that matters.
          example: "2026-08-18T10:00:00+02:00"
        amount:
          type: number
          description: "Deprecated: use `amount_money` instead. Read `amount_money`,
            `percent` or `nights`, whichever this step carries. What the guest
            is charged on or after `cancel_time`: a sum in MAJOR units of
            `currency`, a percentage or a number of nights, as `type` says."
          example: 606.13
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `amount_money` instead. The currency of `amount`."
          example: EUR
          deprecated: true
        type:
          type: string
          description: How the charge is expressed — a sum ("amount", "flat_fee"; read
            `amount_money`), a percentage ("percent", "percentage"; read
            `percent`) or a number of nights ("nights"; read `nights`).
          example: amount
        display:
          type: string
          description: 'Deprecated: use `amount_money` instead. The same figure as a
            string ready to show: the ISO 4217 code, a space, then the amount,
            e.g. "USD 159.77". With decimal_places it is written at exactly that
            scale (value 1561500, JPY, decimal_places 2 is "JPY 15615.00");
            without, at the ISO digits of the currency. Show this; compute with
            the number. Absent when the figure is not money (a cancellation step
            expressed as a percent or a number of nights) or could not be read
            unambiguously.'
          example: EUR 606.13
          deprecated: true
        amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: What the guest is charged on or after `cancel_time`, when this step
                is a sum. Absent on a percentage or nights step, and when the
                supplier named no currency.
        percent:
          type: number
          description: "The charge as a percentage of the stay price, when this step is a
            percentage, on the 0–100 scale the supplier states it in: 50 is half
            the stay price, 100 the whole of it. Never a 0–1 fraction. Absent
            otherwise."
          example: 50
        nights:
          type: number
          description: The charge as a number of nights of the stay, when this step is
            expressed in nights. Absent otherwise.
          example: 1
    TaxLine:
      type: object
      properties:
        amount:
          type: number
          description: "Deprecated: use `amount_money` instead. The tax in MAJOR units of
            `currency`."
          example: 164.49
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `amount_money` instead. The currency of `amount`."
          example: EUR
          deprecated: true
        amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The tax. When the supplier named no currency for the line, it is
                the currency the rate is priced in.
        description:
          type: string
          description: The provider’s own wording for the tax. Free text, not a code.
          example: 19, VAT National taxes on accommodation
        included:
          type: boolean
          description: True when the amount is ALREADY inside `total_amount_money`; false
            when the guest pays it at the property on top. Getting this
            backwards misquotes the trip.
          example: true
        display:
          type: string
          description: 'Deprecated: use `amount_money` instead. The same figure as a
            string ready to show: the ISO 4217 code, a space, then the amount,
            e.g. "USD 159.77". With decimal_places it is written at exactly that
            scale (value 1561500, JPY, decimal_places 2 is "JPY 15615.00");
            without, at the ISO digits of the currency. Show this; compute with
            the number. Absent when the figure is not money (a cancellation step
            expressed as a percent or a number of nights) or could not be read
            unambiguously.'
          example: EUR 164.49
          deprecated: true
    HotelPaymentType:
      type: string
      enum:
        - pay_now
        - pay_at_property
        - deposit
      description: How the rate can be settled. `pay_now` — paid when the booking is
        made. `pay_at_property` — paid to the hotel at the property. `deposit` —
        a deposit is taken.
    HotelRatePromotion:
      type: object
      properties:
        code:
          type: string
        name:
          type: string
        remark:
          type: string
    Occupancy:
      type: object
      properties:
        adults:
          type: integer
          minimum: 1
        children_ages:
          type: array
          items:
            type: integer
            minimum: 0
            maximum: 17
      required:
        - adults
      description: "The party one room is requested or priced for: the number of
        adults and the age of each child."
    HotelBundleRoomPolicy:
      type: object
      properties:
        type:
          type: string
        description:
          type: string
        fee_amount:
          type: number
          description: "Deprecated: use `fee_amount_money` instead. Customer policy fee in
            MAJOR units of `fee_currency`."
          deprecated: true
        fee_currency:
          type: string
          description: "Deprecated: use `fee_amount_money` instead. The currency of
            `fee_amount`."
          deprecated: true
        fee_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Customer cancellation or policy fee, with exact minor units and
                currency precision.
    HotelBundleRoom:
      type: object
      properties:
        occupancy_number:
          type: integer
          minimum: 1
          description: Stable one-based room slot within this bundle.
          example: 1
        room_id:
          type: string
        mapped_room_id:
          type: integer
        room_name:
          type: string
          example: Superior Double
        rate_id:
          type: string
        occupancy:
          $ref: "#/components/schemas/Occupancy"
        board_type:
          type: string
          example: BB
        board_name:
          type: string
          example: Breakfast Included
        max_occupancy:
          type: integer
        taxes_and_fees:
          type: array
          items:
            $ref: "#/components/schemas/TaxLine"
        policies:
          type: array
          items:
            $ref: "#/components/schemas/HotelBundleRoomPolicy"
        is_refundable:
          type: boolean
        cancellation_policy:
          type: array
          items:
            $ref: "#/components/schemas/CancellationStep"
        free_cancellation_until:
          type: string
        payment_types:
          type: array
          items:
            $ref: "#/components/schemas/HotelPaymentType"
          description: How the rate can be settled. Each value appears at most once.
          example: &a8
            - pay_now
        remarks:
          type: string
      required:
        - occupancy_number
        - occupancy
      description: One room of a hotel item — the single room a one-room item books,
        or one slot of a room-bundle rate — with the party it was priced for
        (`occupancy`) and its display and policy details. The containing item
        owns the customer-facing total; supplier net, suggested retail,
        commission and room-local supplier price figures are intentionally not
        part of this public shape.
    HotelRate:
      type: object
      properties:
        offer_id:
          type: string
          description: Legacy rooms[].rates[] compatibility token. New integrations use
            the hotel-level `offers[].trip_item_token`; add that token to the
            trip exactly once.
          example: htl_2d67a7441c60e5de
        board_type:
          type: string
          example: RO
        board_name:
          type: string
          example: Room Only
        total_amount:
          type: number
          description: "Deprecated: use `total_amount_money` instead. Price for the whole
            stay in `currency`, in MAJOR units at the currency’s own precision."
          example: 1818.4
          deprecated: true
        total_amount_display:
          type: string
          description: 'Deprecated: use `total_amount_money` instead. The rate total as a
            string ready to show: the ISO 4217 code, a space, then
            `total_amount` at the currency’s ISO digits, e.g. "EUR 606.13".'
          example: EUR 606.13
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `total_amount_money` instead. The currency of
            `total_amount`."
          example: EUR
          deprecated: true
        total_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Price for the whole stay.
        is_refundable:
          type: boolean
          example: false
        free_cancellation_until:
          type: string
          description: Last instant the stay can be cancelled at no charge. RFC 3339 with
            the supplier’s declared UTC offset. Absent when the supplier
            declared no timezone — the platform never invents an offset, so a
            deadline it cannot place on the clock is withheld rather than
            published ambiguously — and absent when the rate is non-refundable
            or the provider named no deadline.
          example: "2026-08-18T10:00:00+02:00"
        cancellation_schedule:
          type: array
          items:
            $ref: "#/components/schemas/CancellationStep"
          description: The full penalty ladder, chronological. Absent when the provider
            published none — which is not a statement that cancelling is free.
        taxes_breakdown:
          type: array
          items:
            $ref: "#/components/schemas/TaxLine"
          description: Taxes and fees on this rate. ALWAYS present, so an empty array
            means "no tax is known" and can be shown as such; check `included`
            per line before adding anything to `total_amount_money`.
        payment_types:
          type: array
          items:
            $ref: "#/components/schemas/HotelPaymentType"
          description: How the rate can be settled. Each value appears at most once.
          example: *a8
        promotions:
          type: array
          items:
            $ref: "#/components/schemas/HotelRatePromotion"
        booking_scope:
          type: string
          description: LEGACY-ONLY compatibility metadata. Current canonical `offers[]`
            never returns `booking_scope`; use `room_rates.length` to determine
            how many rooms an offer covers.
          example: room_bundle
        num_rooms:
          type: integer
          minimum: 1
          description: LEGACY-ONLY compatibility metadata. Current canonical `offers[]`
            represents room count through `room_rates.length` and never returns
            `num_rooms`.
          example: 2
        rooms:
          type: array
          items:
            $ref: "#/components/schemas/HotelBundleRoom"
          description: LEGACY-ONLY compatibility room details. Current canonical
            `offers[]` returns `room_rates[]` and never returns this `rooms`
            field.
      description: Deprecated compatibility shape under `rooms[].rates[]`. Current
        canonical `offers[]` does not return `booking_scope`, `num_rooms`, or
        `rooms`; use `room_rates[]` instead.
    HotelRoom:
      type: object
      properties:
        room_id:
          type: string
          example: rm_1
        room_name:
          type: string
          example: Superior Double
        description:
          type: string
          description: Free-text room description, when the provider supplied one.
        requested_occupancy:
          type: integer
          description: The occupancy these rates were priced for — an echo of what you
            searched, not a property of the room. Pricing a different party size
            means searching again.
          example: 2
        room_capacity:
          type: integer
          description: How many the room sleeps, from the provider’s content catalogue.
            Absent when the catalogue carries no figure — absent means unknown,
            never zero. Same field as on hotel_details and on a hotel trip item.
          example: 2
        max_occupancy:
          type: integer
          description: "Deprecated: an alias of `requested_occupancy` (same value), never
            the room’s capacity. Read `requested_occupancy` for the priced party
            size and `room_capacity` for how many the room sleeps."
          deprecated: true
          example: 2
        images:
          type: array
          items:
            type: string
        amenities:
          type: array
          items:
            type: string
        beds:
          type: array
          items:
            $ref: "#/components/schemas/HotelBed"
        rates:
          type: array
          items:
            $ref: "#/components/schemas/HotelRate"
          description: DEPRECATED compatibility projection. Read the hotel-level
            `offers[]` list for new integrations and add an offer’s
            `trip_item_token` to the trip. Multi-room searches return this as an
            empty array.
          deprecated: true
    HotelOfferPromotion:
      type: object
      properties:
        name:
          type: string
        remark:
          type: string
      description: "A provider promotion applied to the offer, as it is to be shown to
        the guest: its name and the remark that goes with it."
    HotelRoomRate:
      type: object
      properties:
        room_id:
          type: string
          description: References one entry in this hotel’s `rooms[]` metadata.
        occupancy_number:
          type: integer
          minimum: 1
          description: Stable one-based occupancy slot from the search request.
        occupancy:
          $ref: "#/components/schemas/Occupancy"
        room_name:
          type: string
        board_type:
          type: string
        board_name:
          type: string
        max_occupancy:
          type: integer
        taxes_and_fees:
          type: array
          items:
            $ref: "#/components/schemas/TaxLine"
        policies:
          type: array
          items:
            $ref: "#/components/schemas/HotelBundleRoomPolicy"
        is_refundable:
          type: boolean
        cancellation_policy:
          type: array
          items:
            $ref: "#/components/schemas/CancellationStep"
        free_cancellation_until:
          type: string
        payment_types:
          type: array
          items:
            $ref: "#/components/schemas/HotelPaymentType"
          description: How the rate can be settled. Each value appears at most once.
          example: *a8
        remarks:
          type: string
      required:
        - room_id
        - occupancy_number
        - occupancy
        - taxes_and_fees
        - is_refundable
      description: Display and policy details for one requested room occupancy. It
        carries no customer price allocation; the containing offer owns the
        authoritative whole-stay total.
    HotelOffer:
      type: object
      properties:
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. Same value."
          example: htl_2d67a7441c60e5de
          deprecated: true
        board_type:
          type: string
          example: RO
        board_name:
          type: string
          example: Room Only
        total_amount:
          type: number
          description: "Deprecated: use `total_amount_money` instead. Price for the whole
            stay in `currency`, in MAJOR units at the currency’s own precision."
          example: 1818.4
          deprecated: true
        total_amount_display:
          type: string
          description: 'Deprecated: use `total_amount_money` instead. The rate total as a
            string ready to show: the ISO 4217 code, a space, then
            `total_amount` at the currency’s ISO digits, e.g. "EUR 606.13".'
          example: EUR 606.13
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `total_amount_money` instead. The currency of
            `total_amount`."
          example: EUR
          deprecated: true
        total_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Price for the whole stay.
        is_refundable:
          type: boolean
        free_cancellation_until:
          type: string
          description: Last instant the stay can be cancelled at no charge. RFC 3339 with
            the supplier’s declared UTC offset. Absent when the supplier
            declared no timezone — the platform never invents an offset, so a
            deadline it cannot place on the clock is withheld rather than
            published ambiguously — and absent when the rate is non-refundable
            or the provider named no deadline.
          example: "2026-08-18T10:00:00+02:00"
        cancellation_schedule:
          type: array
          items:
            $ref: "#/components/schemas/CancellationStep"
          description: The full penalty ladder, chronological. Absent when the provider
            published none — which is not a statement that cancelling is free.
        taxes_breakdown:
          type: array
          items:
            $ref: "#/components/schemas/TaxLine"
        payment_types:
          type: array
          items:
            $ref: "#/components/schemas/HotelPaymentType"
          description: How the rate can be settled. Each value appears at most once.
          example: *a8
        promotions:
          type: array
          items:
            $ref: "#/components/schemas/HotelOfferPromotion"
        trip_item_token:
          type: string
          description: The token `trip(add_item)` takes as `trip_item_token`. Add it once
            even when `room_rates` contains several occupancies.
          example: htl_2d67a7441c60e5de
        room_rates:
          type: array
          items:
            $ref: "#/components/schemas/HotelRoomRate"
          description: One entry per requested occupancy. One occupancy means one room;
            multiple occupancies mean a multi-room offer.
      required:
        - offer_id
        - total_amount
        - currency
        - is_refundable
        - taxes_breakdown
        - trip_item_token
        - room_rates
    Hotel:
      type: object
      properties:
        hotel_id:
          type: string
          description: Opaque hotel identifier. Pass it to hotel_details, hotel_reviews
            and `hotel_ids` exactly as received; do not parse or build it. The
            value a hotel is known by can change between contract versions, so
            read it from a fresh hotel_search rather than keeping it.
          example: lp1d2c3
        hotel_ref:
          type: string
          description: "Deprecated: use `hotel_id` (search) or `id` (details, reviews).
            The hotel's identifier behind a source prefix, as earlier contract
            versions returned it; hotel_details and hotel_reviews still accept
            it. Pass it back exactly as received; do not parse or build it."
          example: h1:lp1d2c3
          deprecated: true
        name:
          type: string
          example: Hôtel Le Marais
        address:
          type: string
          example: 12 Rue de Rivoli
        city:
          type: string
          example: Paris
        country:
          type: string
          description: ISO 3166-1 alpha-2 country code, LOWER case as the platform sends it.
          example: fr
        star_rating:
          type: number
          example: 4
        category:
          type: string
          description: The provider's own category wording, which `star_rating` cannot
            express. Free text.
          example: 4 KEYS
        lodging_type:
          type: string
          example: Aparthotel
        rating:
          type: number
          description: Guest score out of 10.
          example: 8.6
        review_count:
          type: number
          description: Number of guest reviews behind `rating`.
          example: 1243
        main_photo:
          type: string
          description: Full-size hero image URL.
          example: https://images.example.com/hotels/main.jpg
        thumbnail:
          type: string
          description: Small preview image URL.
          example: https://images.example.com/hotels/thumb.jpg
        latitude:
          type: number
          example: 48.8566
        longitude:
          type: number
          example: 2.3522
        distance_km:
          type: number
          minimum: 0
          description: Straight-line distance from the search center, in kilometers.
        recommendation_score:
          type: number
          minimum: 0
          maximum: 1
          description: How well the hotel fits the request, from 0 to 1; results are
            ordered by it. Not a guest rating.
        rooms:
          type: array
          items:
            $ref: "#/components/schemas/HotelRoom"
        offers:
          type: array
          items:
            $ref: "#/components/schemas/HotelOffer"
          description: Bookable whole-stay offers. Choose one and add its
            `trip_item_token` to the trip exactly once.
      description: A hotel and its available rooms. Until v0.2.0 this schema declared
        `images`, `thumbnail_url` and `country_code`, none of which hotel search
        has ever sent; the real names are `main_photo`, `thumbnail` and
        `country`.
    HotelAiSearchAnswer:
      type: object
      properties:
        context_id:
          type: string
          nullable: true
          description: The conversation; send it with the next message to continue.
          example: ctx_example
        task_id:
          type: string
          example: atk_example
        status:
          type: string
          enum:
            - working
            - input_required
            - completed
            - failed
            - canceled
          description: "`working`: the search is still running, read the task again.
            `input_required`: the message asks a question; answer it in the same
            conversation. `completed`: the hotels are in the answer. `failed`:
            see `error`. `canceled`: a later message or a cancel replaced it."
        message:
          type: string
          description: The reply to show the traveller.
          example: Found 37 hotels in Paris for Oct 24–25 (1 night, 2 adults, 1 room).
        question:
          type: string
          description: What the reply asks for, when `status` is `input_required`.
          example: dates
        criteria:
          type: object
          additionalProperties:
            nullable: true
          description: The search the request was understood as, in the `hotel_search`
            request fields, plus `board_types` and `refundable_only` for the
            rate filters applied to the results.
        notes:
          type: array
          items:
            type: object
            additionalProperties:
              nullable: true
          description: Assumptions and adjustments made while understanding the request.
        hotels:
          type: array
          items:
            $ref: "#/components/schemas/Hotel"
        has_more:
          type: boolean
          description: More hotels are available; ask for more in the same conversation.
        reference:
          type: boolean
          description: The hotels are a 1-night reference search shown while the check-out
            date is asked.
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
          required:
            - code
            - message
          description: Why the task failed, when `status` is `failed`.
        superseded_by:
          type: string
          description: The task that replaced this one, when `status` is `canceled`.
      required:
        - context_id
        - task_id
        - status
    HotelAiSearchRequest:
      type: object
      properties:
        text:
          type: string
          minLength: 1
          maxLength: 2000
          description: The traveller's request in one sentence, or the answer to the
            question asked in the previous turn.
          example: A hotel in Paris next weekend for 2 adults with breakfast included
        context_id:
          type: string
          minLength: 1
          maxLength: 100
          description: The conversation to continue, from an earlier answer. Omit to start
            a new conversation.
          example: ctx_example
        task_id:
          type: string
          minLength: 1
          maxLength: 100
          description: "The task of that conversation the message answers. Optional:
            without it, a message continues the task waiting for an answer, or
            starts a new one."
          example: atk_example
        currency:
          type: string
          pattern: ^[A-Za-z]{3}$
          description: Currency of the prices (ISO 4217).
          example: EUR
        guest_nationality:
          type: string
          pattern: ^[A-Za-z]{2}$
          description: Nationality of the guests (ISO 3166-1 alpha-2).
          example: FR
        timezone:
          type: string
          description: The traveller's IANA time zone. Relative dates such as "next
            weekend" or "tonight" are computed in it.
          example: Europe/Paris
      required:
        - text
        - timezone
    DestinationSuggestion:
      type: object
      properties:
        city_name:
          type: string
          example: Paris
        iata_code:
          type: string
          example: PAR
        image_url:
          type: string
          example: https://images.gojinko.com/destinations/par.jpg
        location:
          type: object
          properties:
            latitude:
              type: number
            longitude:
              type: number
          required:
            - latitude
            - longitude
          example:
            latitude: 48.8566
            longitude: 2.3522
        lowest_fare:
          allOf:
            - $ref: "#/components/schemas/Itinerary"
            - description: "One adult's fare (`priced_for: \"one_adult\"`): the cache holds
                one-adult fares only."
        flights:
          type: array
          items:
            $ref: "#/components/schemas/Itinerary"
          description: "One adult's fare (`priced_for: \"one_adult\"`): the cache holds
            one-adult fares only."
      required:
        - flights
    FindDestinationResponse:
      type: object
      properties:
        priced_for:
          type: string
          enum:
            - one_adult
          description: "Whose price the cached fares in this answer are: always
            `one_adult`. Every cached total is one adult's fare; this request
            takes no passenger counts. Price the whole party with `POST
            /v1/flight_search`."
          example: one_adult
        destinations:
          type: array
          items:
            $ref: "#/components/schemas/DestinationSuggestion"
        total:
          type: number
          example: 12
        next_page_token:
          type: string
          example: eyJvZmZzZXQiOjIwfQ==
      required:
        - priced_for
        - destinations
    DateRange:
      type: object
      properties:
        start:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        end:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
      required:
        - start
        - end
      description: Inclusive range of dates. `start` must be on or before `end`; a
        one-day range has `start` equal to `end`.
      example:
        start: "2026-06-01"
        end: "2026-06-30"
    IntentInput:
      type: object
      properties:
        user_intent:
          type: string
          nullable: true
          description: "The user's natural-language intent: the Alpic PII-stripped
            paraphrase when available, else a best-effort fallback to the
            client-provided NL query."
          example: find a cheap flight to Tokyo
    FindDestinationRequest:
      type: object
      properties:
        origins:
          type: array
          items:
            type: string
          minItems: 1
          description: IATA city or airport codes. See `origin_type` for how an untyped
            code is read.
          example: &a10
            - NYC
        destinations:
          type: array
          items:
            type: string
          description: IATA city or airport codes. Omit for global discovery
            (`find_destination`) or to scan every destination from the origins.
            See `destination_type` for how an untyped code is read.
          example: &a11
            - PAR
        origin_type:
          type: string
          enum: &a9
            - city
            - airport
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
          example: city
        destination_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
          example: city
        departure_dates:
          type: array
          items:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          example: &a12
            - "2026-07-15"
        departure_date_ranges:
          type: array
          items:
            $ref: "#/components/schemas/DateRange"
        return_dates:
          type: array
          items:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          example: &a13
            - "2026-07-22"
        return_date_ranges:
          type: array
          items:
            $ref: "#/components/schemas/DateRange"
        stay_days:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          example: 7
        stay_days_range:
          type: object
          properties:
            min:
              type: integer
            max:
              type: integer
          required:
            - min
            - max
        trip_type:
          type: string
          enum: &a14
            - oneway
            - roundtrip
          example: roundtrip
        cabin_class:
          type: string
          enum: &a15
            - economy
            - premium_economy
            - business
            - first
          example: economy
        direct_only:
          type: boolean
          description: Only direct flights. Cached fares record whether a fare is direct
            but not how many stops it makes, so this is the only stop filter
            here; POST /v1/flight_search takes `max_stops`.
          example: false
        accuracy:
          type: string
          enum: &a16
            - standard
            - high
          description: How strict the freshness check on cached fares is. `standard`
            (default) returns fares estimated to be at least 80% likely to still
            be available at the cached price; `high` raises that to 95%, so
            fewer fares come back.
          example: standard
        max_total:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: Caps the cached fare's total. Cached fares are priced for one adult.
          example: 800
        currency:
          type: string
          example: USD
        locale:
          type: string
          example: en-US
        limit:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: "The maximum number of destinations returned, 1 to 100, default 20.
            It counts destinations, not itineraries: each destination carries up
            to `flights_per_destination` itineraries."
        offset:
          type: integer
          minimum: 0
          default: 0
        sort_by:
          type: string
          enum: &a17
            - lowest
            - recommendation
          default: lowest
        intent:
          $ref: "#/components/schemas/IntentInput"
        flights_per_destination:
          type: integer
          minimum: 1
          maximum: 10
          default: 1
      required:
        - origins
        - trip_type
      example:
        origins:
          - NYC
        trip_type: roundtrip
        departure_date_ranges:
          - start: "2026-09-01"
            end: "2026-09-30"
        stay_days: 7
        cabin_class: economy
        max_total: 800
        currency: USD
        flights_per_destination: 1
    FlightCalendarResponse:
      type: object
      properties:
        priced_for:
          type: string
          enum:
            - one_adult
          description: "Whose price the cached fares in this answer are: always
            `one_adult`. Every cached total is one adult's fare; this request
            takes no passenger counts. Price the whole party with `POST
            /v1/flight_search`."
          example: one_adult
        itineraries:
          type: array
          items:
            $ref: "#/components/schemas/Itinerary"
        next_page_token:
          type: string
          example: eyJvZmZzZXQiOjIwfQ==
      required:
        - priced_for
        - itineraries
    FlightDiscoveryRequest:
      type: object
      properties:
        origins:
          type: array
          items:
            type: string
          minItems: 1
          description: IATA city or airport codes. See `origin_type` for how an untyped
            code is read.
          example: *a10
        destinations:
          type: array
          items:
            type: string
          description: IATA city or airport codes. Omit for global discovery
            (`find_destination`) or to scan every destination from the origins.
            See `destination_type` for how an untyped code is read.
          example: *a11
        origin_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
          example: city
        destination_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
          example: city
        departure_dates:
          type: array
          items:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          example: *a12
        departure_date_ranges:
          type: array
          items:
            $ref: "#/components/schemas/DateRange"
        return_dates:
          type: array
          items:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          example: *a13
        return_date_ranges:
          type: array
          items:
            $ref: "#/components/schemas/DateRange"
        stay_days:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          example: 7
        stay_days_range:
          type: object
          properties:
            min:
              type: integer
            max:
              type: integer
          required:
            - min
            - max
        trip_type:
          type: string
          enum: *a14
          example: roundtrip
        cabin_class:
          type: string
          enum: *a15
          example: economy
        direct_only:
          type: boolean
          description: Only direct flights. Cached fares record whether a fare is direct
            but not how many stops it makes, so this is the only stop filter
            here; POST /v1/flight_search takes `max_stops`.
          example: false
        accuracy:
          type: string
          enum: *a16
          description: How strict the freshness check on cached fares is. `standard`
            (default) returns fares estimated to be at least 80% likely to still
            be available at the cached price; `high` raises that to 95%, so
            fewer fares come back.
          example: standard
        max_total:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: Caps the cached fare's total. Cached fares are priced for one adult.
          example: 800
        currency:
          type: string
          example: USD
        locale:
          type: string
          example: en-US
        limit:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: "What `limit` counts depends on the route; 1 to 100, default 20. On
            `flight_calendar`, the maximum number of itineraries returned across
            the entire matching date range after `sort_by` is applied. This is a
            global result cap, not one itinerary per date pair: with the default
            `sort_by: lowest`, `limit: N` returns the cheapest N itineraries
            overall, so some matching date pairs may be absent. On `find_dates`,
            the maximum number of date pairs, each answered with its cheapest
            itinerary and spread across the requested departure window. On
            `lowest_fare`, not applied: that route returns at most ten
            itineraries, cheapest first."
        offset:
          type: integer
          minimum: 0
          default: 0
        sort_by:
          type: string
          enum: *a17
          default: lowest
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - origins
        - trip_type
      example:
        origins:
          - NYC
        destinations:
          - PAR
        trip_type: roundtrip
        departure_date_ranges:
          - start: "2026-09-01"
            end: "2026-09-30"
        stay_days: 7
        cabin_class: economy
        currency: USD
    Money:
      type: object
      properties:
        amount:
          type: number
          description: "Deprecated: use `value` instead (the same integer) where this
            object carries decimal_places. Where it does not, the figure is in
            MAJOR units and the field holding this object is itself deprecated:
            read its `*_money` sibling. The two-scale rule applies only to
            deprecated fields. Alternative to `value` on some endpoints (the two
            never appear together); its scale depends on decimal_places. When
            this object carries decimal_places, amount is an INTEGER in minor
            units — divide by 10 ** decimal_places (e.g. select_ancillaries
            total_with_ancillaries). When there is no decimal_places field,
            amount is a decimal in MAJOR units, safe to display as-is (e.g. trip
            and checkout totals)."
          deprecated: true
        value:
          type: integer
          description: "Integer amount in MINOR units, always paired with decimal_places —
            divide by 10 ** decimal_places to display. Example: value 15977 with
            decimal_places 2 is 159.77 USD. Rendering this field directly shows
            prices 100x too high for 2-decimal currencies."
          example: 41250
        currency:
          type: string
          description: ISO 4217 currency code.
          example: USD
        decimal_places:
          type: integer
          description: "Scale of the integer value/amount: display = integer / 10 **
            decimal_places. Always sent alongside minor-unit amounts. Usually
            the ISO 4217 digits of the currency (2 for USD/EUR/GBP, 0 for
            JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices can carry
            a different scale — ALWAYS use the decimal_places sent with the
            amount, never a hardcoded 2. Only if the field is genuinely absent
            on a value-shaped object, fall back to the ISO digits for the
            currency."
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount, e.g. "USD 159.77". With decimal_places it is
            written at exactly that scale (value 1561500, JPY, decimal_places 2
            is "JPY 15615.00"); without, at the ISO digits of the currency. Show
            this; compute with the number. Absent when the figure is not money
            (a cancellation step expressed as a percent or a number of nights)
            or could not be read unambiguously.'
          example: USD 412.50
      description: "A money figure in one of two scales. New integrations read the
        `*_money` field beside it (a `MoneyValue`) where there is one, and
        `value` on objects that carry it; the rule below applies only to the
        deprecated forms. When `decimal_places` is present, `value` (or the
        deprecated `amount`) is an INTEGER in minor units: divide by 10 **
        decimal_places. When it is absent, the deprecated `amount` is already in
        MAJOR units. Branch on whether decimal_places is present in the response
        you received, never on the currency code or the field name. `display` is
        the same figure as a string to show."
    MoneyWithoutAmount:
      type: object
      properties:
        value:
          type: integer
          description: "Integer amount in MINOR units, always paired with decimal_places —
            divide by 10 ** decimal_places to display. Example: value 15977 with
            decimal_places 2 is 159.77 USD. Rendering this field directly shows
            prices 100x too high for 2-decimal currencies."
          example: 41250
        currency:
          type: string
          description: ISO 4217 currency code.
          example: USD
        decimal_places:
          type: integer
          description: "Scale of the integer value/amount: display = integer / 10 **
            decimal_places. Always sent alongside minor-unit amounts. Usually
            the ISO 4217 digits of the currency (2 for USD/EUR/GBP, 0 for
            JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices can carry
            a different scale — ALWAYS use the decimal_places sent with the
            amount, never a hardcoded 2. Only if the field is genuinely absent
            on a value-shaped object, fall back to the ISO digits for the
            currency."
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount, e.g. "USD 159.77". With decimal_places it is
            written at exactly that scale (value 1561500, JPY, decimal_places 2
            is "JPY 15615.00"); without, at the ISO digits of the currency. Show
            this; compute with the number. Absent when the figure is not money
            (a cancellation step expressed as a percent or a number of nights)
            or could not be read unambiguously.'
          example: USD 412.50
      description: "A money figure: `value` is an INTEGER in minor units (divide by 10
        ** `decimal_places` to get the amount), `currency` is its ISO 4217 code
        and `display` is the same figure as a string ready to show. The `Money`
        shape without its deprecated `amount` member, for a figure that never
        carried one."
    Fare:
      type: object
      properties:
        trip_item_token:
          type: string
          description: "The token that adds this fare to a trip: pass it to `POST
            /v1/trip` as `add_item.trip_item_token`. Opaque: the offer’s
            `offer_id`, a colon, then the provider’s reference for the fare.
            Usable until `expires_at`; after that, search again and use the
            fresh token."
          example: offer__3a9f1b27:0-1-0
        searched_at:
          type: string
          format: date-time
          description: When the supplier search for this fare began, in RFC 3339 format.
            Repeated searches can return the same trip_item_token; use this
            timestamp to assess freshness. Absent when the search time is
            unknown.
          example: "2026-09-23T15:43:40Z"
        expires_at:
          type: string
          format: date-time
          description: "Latest known time to use this fare, in RFC 3339 format: the
            earlier of the supplier deadline, when supplied, and Jinko’s
            75-minute token lifetime measured from searched_at. Without a
            supplier deadline this bounds token retention only. Availability and
            price can change sooner. Complete checkout promptly; after this
            time, search again and use the latest result. Absent means unknown,
            not unlimited validity. This is not a quote or payment deadline."
          example: "2026-09-23T16:58:40Z"
        cabin_class:
          type: string
          description: "The cabin this fare sells: `economy`, `premium_economy`,
            `business` or `first`. For a fare over several flight segments it is
            the cabin of the main segment — the longest flight — since a short
            connecting segment can sit in another cabin."
          example: economy
        brand_name:
          type: string
          description: The fare brand as the airline names it, read from the first segment
            that carries a fare component; when the provider names no brand, the
            cabin name it sent instead. Absent when neither is known.
          example: Main Cabin
        total_price:
          $ref: "#/components/schemas/Money"
        price_per_person:
          $ref: "#/components/schemas/MoneyWithoutAmount"
        included_baggage:
          allOf:
            - $ref: "#/components/schemas/CheckedBaggage"
            - description: "Checked-bag allowance of this fare, read from the first segment
                that states one (it is not reported per leg). Absent when no
                segment states a checked-bag allowance; a stated zero is sent as
                `pieces: 0`."
        carry_on_baggage:
          allOf:
            - $ref: "#/components/schemas/CheckedBaggage"
            - description: Cabin-bag allowance of this fare, read from the first segment that
                states a carry-on bag or a personal item (it is not reported per
                leg). Absent when no segment states one.
        is_changeable:
          type: boolean
          description: "Whether the fare allows a voluntary change, folded from every
            change rule of the itinerary (the most restrictive wins). Not the
            same reading as the `changeable_only` filter: the filter checks the
            before-departure rules only, while this flag is `true` on a fare
            whose only decided rule allows a change after departure
            (`change_policy` then ends in `after departure`). `false` is an
            answer: the fare rules did not confirm a change is allowed."
          example: true
        is_refundable:
          type: boolean
          description: "Whether the fare can be cancelled, with or without a fee, folded
            from every cancellation rule of the itinerary (the most restrictive
            wins). Not the same reading as the `refundable_only` filter: the
            filter checks the before-departure rules only, while this flag is
            `true` on a fare whose only decided rule allows cancellation after
            departure (`refund_policy` then ends in `after departure`). `false`
            is an answer: the fare rules did not confirm a refund is allowed."
          example: false
        refund_policy:
          type: string
          description: "The refund terms in words, before booking: `Free cancellation`,
            `Refundable` (fee not stated), `Refundable with fee` or
            `Non-refundable`; when the only decided rule applies after
            departure, the same four with ` after departure` appended, e.g.
            `Refundable with fee after departure`. A cancellation rule with an
            unspecified penalty reads `Non-refundable`. Absent when the fare
            carries no cancellation rule. Read it beside `is_refundable`, which
            says only whether a refund is possible at all."
          example: Refundable with fee
        change_policy:
          type: string
          description: "The change terms in words, before booking: `Free changes`,
            `Changes allowed` (fee not stated), `Changes allowed with fee` or
            `No changes allowed`; when the only decided rule applies after
            departure, the same four with ` after departure` appended, e.g.
            `Changes allowed with fee after departure`. Absent when the fare
            carries no change rule, or only one with an unspecified penalty.
            Read it beside `is_changeable`, which says only whether a change is
            possible at all."
          example: Changes allowed with fee
        checked_bag_included:
          type: boolean
          description: "Whether the price already includes at least one free checked bag,
            read from `included_baggage`: `pieces` is 1 or more.
            `included_baggage` comes from the first segment that states an
            allowance, so this is not the same reading as the
            `checked_bag_included` filter, which needs a free bag on every
            segment. `weight` is the per-bag limit that applies when a bag IS
            included, so it carries no allowance on its own; prose in
            `included_baggage` does not count either."
          example: true
    FlightOffer:
      type: object
      properties:
        offer_id:
          type: string
          description: "Identifier of this offer: `offer__` followed by 8 hex characters.
            Send it as `offer_token` to re-price the offer; it is also the
            prefix of each fare’s `trip_item_token`."
          example: offer__3a9f1b27
        origin:
          type: object
          properties:
            code:
              type: string
              description: "City code of the requested origin: the code sent as `origin` when
                it was typed `city`, otherwise the city of that airport (`NYC`
                for JFK). Not the airport flown; read `outbound.origin` for
                that. An empty string when the platform cannot map the requested
                code to a city."
            name:
              type: string
          example:
            code: NYC
            name: New York
        destination:
          type: object
          properties:
            code:
              type: string
              description: City code of the requested destination, resolved as `origin.code`
                is. Not the airport flown; read `outbound.destination` for that.
                An empty string when the platform cannot map the requested code
                to a city.
            name:
              type: string
          example:
            code: LAX
            name: Los Angeles
        is_round_trip:
          type: boolean
          example: false
        total_duration_minutes:
          type: number
          example: 385
        outbound:
          $ref: "#/components/schemas/FlightLeg"
        inbound:
          $ref: "#/components/schemas/FlightLeg"
        additional_legs:
          type: array
          items:
            $ref: "#/components/schemas/FlightLeg"
          description: Third and later legs of a multi-city itinerary, in travel order.
            Empty for one-way and round-trip offers.
          example: []
        fares:
          type: array
          items:
            $ref: "#/components/schemas/Fare"
      required:
        - offer_id
        - origin
        - destination
        - additional_legs
        - fares
    FlightSearchResponse:
      type: object
      properties:
        offers:
          type: array
          items:
            $ref: "#/components/schemas/FlightOffer"
        exact_match_found:
          type: boolean
          description: "Price-check mode only (request carried `offer_token`): true when
            the live offer has the same flights as the cached one. Absent in
            search mode."
          example: true
        result:
          type: string
          enum:
            - no_matches
          description: "Search mode only. `no_matches` means the search completed and no
            offer matched: relay `instruction`, which asks which filter to relax
            only when the request sent a filter that narrows the results.
            `offers` is empty. Absent when offers were found. A search that
            could not be completed at all answers an error instead
            (`UPSTREAM_REJECTED`, `UPSTREAM_ERROR`, `UPSTREAM_UNAVAILABLE` or
            `UPSTREAM_TIMEOUT`), never an empty list."
        instruction:
          type: string
          description: 'Present with `result: no_matches`: what to tell the user or do
            next. It attributes the empty result to the filters only when the
            request sent a filter that narrows the results; otherwise it reads
            "Search completed successfully, but no flights were found for this
            route and dates. Ask the user whether to try other dates or airports
            before searching again."'
          example: "Search completed successfully, but no offers satisfied every filter
            sent: the filter combination is too restrictive for this route and
            dates. Ask the user which filter to relax before searching again."
      required:
        - offers
    FlightSearchRequest:
      type: object
      properties:
        origin:
          type: string
          description: "3-letter IATA city or airport code. See `origin_type` for how an
            untyped code is read. `origin` and `destination` must differ. A
            3-letter code the platform’s location catalog does not recognise is
            not refused: it is searched as an airport, and if no provider sells
            it the search answers `result: no_matches`."
          example: JFK
        destination:
          type: string
          description: '3-letter IATA city or airport code. See `destination_type` for how
            an untyped code is read: LAX alone is the Los Angeles CITY; send
            `destination_type: "airport"` for the airport only. `origin` and
            `destination` must differ. A 3-letter code the platform’s location
            catalog does not recognise is not refused: it is searched as an
            airport, and if no provider sells it the search answers `result:
            no_matches`.'
          example: LAX
        origin_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field. The provider decides which airports a city holds, so
            a city search can return airports the catalog does not list under
            that code: searched as a city, LAX returns Ontario (ONT) fares,
            often as the cheapest offers. Each offer’s legs carry the airports
            flown; the offer-level `origin` / `destination` carry the city."
          example: airport
        destination_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field. The provider decides which airports a city holds, so
            a city search can return airports the catalog does not list under
            that code: searched as a city, LAX returns Ontario (ONT) fares,
            often as the cheapest offers. Each offer’s legs carry the airports
            flown; the offer-level `origin` / `destination` carry the city."
          example: airport
        departure_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: "Departure date, `YYYY-MM-DD`: the local date at `origin`. Required
            in search mode, with `origin` and `destination`; not allowed beside
            `offer_token`. A date that does not exist on the calendar
            (`2026-02-30`) is refused with 422 naming the field."
          example: "2026-09-01"
        return_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Return date, `YYYY-MM-DD`, on or after `departure_date` (a same-day
            return is valid). Sending it makes the search a round trip; see
            `trip_type`.
        trip_type:
          type: string
          enum: *a14
          description: "`oneway` or `roundtrip`. Omit it and `return_date` decides:
            present is a round trip, absent a one-way trip. `roundtrip` requires
            `return_date`, and `oneway` refuses it (422 naming `return_date`)."
        cabin_class:
          type: string
          nullable: true
          enum: *a15
          description: Omit this field or send `null` to let the provider default the
            search to economy without applying a cabin filter. Send an explicit
            enum value to require each fare’s representative cabin to equal it.
            The representative cabin is the cabin on the longest flight segment;
            shorter connecting segments may use another cabin. An omitted or
            `null` cabin applies no cabin filter.
          example: economy
        direct_only:
          type: boolean
          description: "DEPRECATED — send `max_stops: 0` instead. Still accepted:
            `direct_only` is folded into `max_stops` (`true` becomes `max_stops:
            0`) before the search runs, so only `max_stops` reaches the
            platform. Setting it beside a non-zero `max_stops` is rejected."
          deprecated: true
          example: false
        max_stops:
          type: integer
          minimum: 0
          maximum: 2
          description: "Maximum stops per leg: `0` non-stop (the way to ask for direct
            flights), `1` one connection, `2` two. Applies to every leg of the
            trip."
          example: 1
        multi_fare:
          type: boolean
          description: "Branded fare ladder: several fares per itinerary (upsell options).
            Defaults to `true` when omitted; send `false` for a single fare per
            itinerary and a smaller response. An offer carries at most 10 fares,
            the cheapest fare of each cabin kept first; a provider that sells no
            fare ladder returns a single fare either way."
          example: true
        max_total:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: "Drop fares whose total price (all passengers) exceeds this cap, in
            `currency`, major units. A fare priced in another currency is
            usually converted to `currency` with the platform’s FX rate before
            the comparison, but not always: a provider whose first priced offer
            is already in `currency` drops its offers in other currencies as
            unverifiable instead of converting them. A fare whose currency
            cannot be converted is not returned."
          example: 800
        include_carriers:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z0-9]{2}$
          description: "Keep only itineraries marketed by these IATA carriers. Matching
            means every segment is marketed by a listed carrier (codeshares
            count by marketing carrier). When nothing matches, the search
            returns no offers with `result: no_matches`; the platform never
            widens to other carriers."
          example:
            - AF
            - DL
        exclude_carriers:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z0-9]{2}$
          description: Drop itineraries marketed by these IATA carriers. Must not overlap
            `include_carriers`.
          example:
            - NK
        departure_time_range:
          allOf:
            - $ref: "#/components/schemas/TimeRange"
            - description: Filter the OUTBOUND leg by local departure time-of-day.
        arrival_time_range:
          allOf:
            - $ref: "#/components/schemas/TimeRange"
            - description: Filter the OUTBOUND leg by local arrival time-of-day.
        return_departure_time_range:
          allOf:
            - $ref: "#/components/schemas/TimeRange"
            - description: Filter the RETURN leg by local departure time-of-day (round-trip
                only).
        return_arrival_time_range:
          allOf:
            - $ref: "#/components/schemas/TimeRange"
            - description: Filter the RETURN leg by local arrival time-of-day (round-trip
                only).
        connection_time_min_minutes:
          type: integer
          minimum: 0
          description: "Shortest acceptable layover, in minutes, applied to every
            connection of every leg. Must not exceed
            `connection_time_max_minutes`. Conservative, like `refundable_only`:
            an itinerary with a connection whose times are unknown cannot be
            checked and is dropped."
          example: 60
        connection_time_max_minutes:
          type: integer
          minimum: 0
          description: "Longest acceptable layover, in minutes, applied to every
            connection of every leg. Conservative in the same way as
            `connection_time_min_minutes`: a connection whose times are unknown
            drops the itinerary."
          example: 240
        max_total_duration_minutes:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          description: Cap each leg’s door-to-door elapsed travel time, in minutes.
          example: 900
        refundable_only:
          type: boolean
          description: "Keep only fares that can be cancelled before departure (with or
            without a fee). Conservative: a fare whose rules the platform cannot
            verify is DROPPED, so carriers that publish no rule data disappear
            under this filter. The filter reads the before-departure
            cancellation rules only; `is_refundable` on a returned fare is a
            wider reading of the same rules (it is `true` on a fare whose only
            decided rule allows cancellation after departure), so the flag is
            not this filter."
          example: true
        changeable_only:
          type: boolean
          description: "Keep only fares that allow a voluntary change. Conservative in the
            same way as `refundable_only`: unverifiable fares are dropped. The
            filter reads the before-departure change rules only; `is_changeable`
            on a returned fare is the wider reading `refundable_only`
            describes."
          example: true
        checked_bag_included:
          type: boolean
          description: "Keep only fares whose price already includes a checked bag on
            EVERY segment. Conservative, like `refundable_only`: a segment that
            states no allowance makes the fare unverifiable and it is dropped.
            The response flag of the same name is read from the first segment
            that states an allowance, not from every segment, so without this
            filter a fare flagged `checked_bag_included: true` can still lack a
            free bag on a later segment."
          example: true
        single_carrier_only:
          type: boolean
          description: Keep only itineraries marketed end-to-end by one carrier.
          example: true
        via_airports:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z]{3}$
          description: "Restrict connections to these airports: an itinerary qualifies
            only when EVERY connection is one of them. Non-stop itineraries have
            no connection to check and are kept. Some providers are asked for at
            most the first 9 listed airports per leg; the whole list is still
            applied to what they return."
          example:
            - AMS
        exclude_via_airports:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z]{3}$
          description: Ban connections at these airports. Must not overlap `via_airports`.
          example:
            - LHR
        aircraft_types:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z0-9]{3}$
          description: "Keep only itineraries whose every segment flies one of these IATA
            equipment codes. Conservative, like `refundable_only`: a segment
            whose equipment is unknown makes the itinerary unverifiable and it
            is dropped, so a provider that reports no equipment (see `aircraft`
            on the segment) disappears under this filter entirely."
          example:
            - "320"
            - 77W
        origin_alternate_airports:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z]{3}$
          description: "ADDITIONAL departure airports searched alongside `origin`.
            Widening only — the anchor in `origin` is always searched, so this
            can add results but never remove any. THE ANCHOR DECIDES RANKING AND
            TRUNCATION, which makes the two airports NOT interchangeable:
            measured on one route, anchor `JFK` with alternate `EWR` returned 15
            JFK / 35 EWR, while anchor `EWR` with alternate `JFK` returned 2 JFK
            / 48 EWR — 13 itineraries differed between the two. Put the airport
            that matters most in `origin`. Works with an airport or a city
            anchor: `origin` NYC with `[\"BOS\"]` searches New York's airports
            and Boston; an alternate inside the city is redundant and harmless.
            On a round trip the platform mirrors the list onto the return leg,
            so it also covers where the return lands. Some providers search only
            the anchor."
          example:
            - EWR
            - LGA
        destination_alternate_airports:
          type: array
          items:
            type: string
            pattern: ^[A-Za-z]{3}$
          description: "ADDITIONAL arrival airports searched alongside `destination`.
            Widening only — the anchor in `destination` is always searched, so
            this can add results but never remove any. THE ANCHOR DECIDES
            RANKING AND TRUNCATION, which makes the two airports NOT
            interchangeable the same way `origin_alternate_airports` describes:
            put the airport that matters most in `destination`. Works with an
            airport or a city anchor, as `origin_alternate_airports` describes.
            On a round trip the platform mirrors the list onto the return leg,
            so it also covers where the return departs from. Some providers
            search only the anchor."
          example:
            - ORY
        nearby_airports:
          type: boolean
          description: "Also search the alternate airports around each leg’s origin and
            destination. Widening: more results, not fewer."
          example: true
        same_connection_airport_only:
          type: boolean
          description: Keep only itineraries whose connections leave from the same airport
            they arrived at (no cross-town transfer).
          example: true
        same_origin_airport_only:
          type: boolean
          description: "Keep only round trips that return to the airport the trip departed
            from. Round trip only: on a one-way search it is accepted and has no
            effect."
          example: true
        same_turnaround_airport_only:
          type: boolean
          description: "Keep only round trips whose return departs from the airport the
            outbound arrived at. Round trip only: on a one-way search it is
            accepted and has no effect."
          example: true
        limit:
          type: integer
          minimum: 1
          maximum: 300
          description: "TOTAL number of flights to return (1–300), not a per-page size:
            `limit: 5` returns at most five flights. Search mode only. Omit to
            let the platform choose: the cheapest flight plus up to 100
            alternatives, so up to 101 flights. Applied after the cross-provider
            merge and sort, so it only trims the returned set — the providers
            still bound the real count."
          example: 20
        adults:
          type: integer
          minimum: 1
          default: 1
          description: "Adult travelers (12+). At most 9 travellers who need a seat:
            `adults + children` ≤ 9. Lap infants are not counted."
        children:
          type: integer
          minimum: 0
          description: "Child travelers (2–11). At most 9 travellers who need a seat:
            `adults + children` ≤ 9. Lap infants are not counted."
        infants:
          type: integer
          minimum: 0
          description: Infant travelers (under 2), traveling on an adult’s lap. Seated
            infants (own seat) are not supported.
        currency:
          type: string
          description: "ISO 4217 currency code, case-insensitive (`eur` is `EUR`): prices
            come back with the upper-case code and a `display`. Defaults to USD.
            A currency the platform cannot price in is refused with 400."
        locale:
          type: string
        offer_token:
          type: string
          description: "Price-check mode: re-price one known offer instead of searching a
            route. Route and filter fields are not allowed beside it (422); the
            passenger counts and `currency` are. Two kinds of token behave
            differently. A cached-itinerary `offer_token` from
            `flight_calendar`, `find_dates`, `lowest_fare`, `find_destination`
            or a price monitor is re-shopped LIVE on its route and dates with no
            cabin, stop or carrier constraint: `offers[0]` is the cheapest live
            offer with the same flights and cabin when one exists,
            `exact_match_found` says whether it did, and up to 100 alternatives
            follow. An `offer_id` from an earlier `flight_search` is answered
            from the cache of that search without re-pricing
            (`exact_match_found: true`), unless the passenger counts or
            `currency` differ, in which case it is re-shopped; once every fare
            of the cached offer has passed its `expires_at` it answers `410
            OFFER_EXPIRED`: search again."
          example: offer__3a9f1b27
        intent:
          $ref: "#/components/schemas/IntentInput"
      example:
        origin: JFK
        destination: CDG
        departure_date: "2026-09-01"
        return_date: "2026-09-08"
        trip_type: roundtrip
        cabin_class: economy
        adults: 1
        max_stops: 1
        checked_bag_included: true
        currency: USD
    MonitoredCarrier:
      type: object
      properties:
        code:
          type: string
          example: DL
        name:
          type: string
          example: Delta Air Lines
        flight_number:
          type: string
          description: Provider flight number, forwarded unchanged. Depending on the
            upstream provider it may be a bare number such as `460` or a
            composed designator such as `AS460`; the carrier code is also
            carried separately when known.
          example: "263"
    MonitoredFlight:
      type: object
      properties:
        offer_token:
          type: string
          example: oft_7c2e9a1b4d
        total_price:
          allOf:
            - $ref: "#/components/schemas/MonitoredMoney"
            - description: "One adult's fare (`priced_for: \"one_adult\"`): the cache holds
                one-adult fares only. To price the whole party, pass
                `offer_token` to `POST /v1/flight_search` with the party."
        outbound_carrier:
          $ref: "#/components/schemas/MonitoredCarrier"
        inbound_carrier:
          $ref: "#/components/schemas/MonitoredCarrier"
        outbound_stops:
          type: number
          description: Number of stops on the outbound journey. Always sent, `0` for a
            non-stop.
          example: 0
        inbound_stops:
          type: number
          description: Number of stops on the return journey. Omitted on a one-way monitor
            and, unlike `outbound_stops`, also when the return is non-stop. When
            a return leg is present (`inbound_departure_local` is sent), read an
            absent `inbound_stops` as `0`.
          example: 1
        outbound_duration_minutes:
          type: number
          example: 470
        inbound_duration_minutes:
          type: number
          example: 520
        outbound_departure_local:
          type: string
          description: "Local time at the airport, RFC 3339 WITH that airport’s UTC offset
            (e.g. `2026-07-15T10:15:00-04:00`), despite the `_local` suffix: the
            same kind of instant as the datetimes on a cached itinerary leg, not
            the zone-less `*_local` wall-clock fields of a booked or exchanged
            itinerary. Parse it as an instant; do not assume UTC and do not
            compare two of these as strings. On the rare airport whose timezone
            the platform does not know, the value keeps its local wall-clock
            digits but is written as UTC (`…Z`)."
          example: "2026-07-15T10:15:00-04:00"
        outbound_arrival_local:
          type: string
          description: "Local time at the airport, RFC 3339 WITH that airport’s UTC offset
            (e.g. `2026-07-15T10:15:00-04:00`), despite the `_local` suffix: the
            same kind of instant as the datetimes on a cached itinerary leg, not
            the zone-less `*_local` wall-clock fields of a booked or exchanged
            itinerary. Parse it as an instant; do not assume UTC and do not
            compare two of these as strings. On the rare airport whose timezone
            the platform does not know, the value keeps its local wall-clock
            digits but is written as UTC (`…Z`)."
          example: "2026-07-15T13:05:00-07:00"
        inbound_departure_local:
          type: string
          description: "Local time at the airport, RFC 3339 WITH that airport’s UTC offset
            (e.g. `2026-07-15T10:15:00-04:00`), despite the `_local` suffix: the
            same kind of instant as the datetimes on a cached itinerary leg, not
            the zone-less `*_local` wall-clock fields of a booked or exchanged
            itinerary. Parse it as an instant; do not assume UTC and do not
            compare two of these as strings. On the rare airport whose timezone
            the platform does not know, the value keeps its local wall-clock
            digits but is written as UTC (`…Z`)."
          example: "2026-07-22T17:40:00-07:00"
        inbound_arrival_local:
          type: string
          description: "Local time at the airport, RFC 3339 WITH that airport’s UTC offset
            (e.g. `2026-07-15T10:15:00-04:00`), despite the `_local` suffix: the
            same kind of instant as the datetimes on a cached itinerary leg, not
            the zone-less `*_local` wall-clock fields of a booked or exchanged
            itinerary. Parse it as an instant; do not assume UTC and do not
            compare two of these as strings. On the rare airport whose timezone
            the platform does not know, the value keeps its local wall-clock
            digits but is written as UTC (`…Z`)."
          example: "2026-07-23T07:25:00-04:00"
        cabin_class:
          type: string
          example: economy
        fare_brand:
          type: string
          example: Main
    PriceMonitoringResponse:
      type: object
      properties:
        priced_for:
          type: string
          enum:
            - one_adult
          description: "Whose price the cached fares in this answer are: always
            `one_adult`. Every cached total is one adult's fare; this request
            takes no passenger counts. Price the whole party with `POST
            /v1/flight_search`."
          example: one_adult
        status:
          type: string
          enum:
            - ok
            - stale
          description: "`ok`: the cache held a matching itinerary and the cheapest is in
            `flight`. `stale`: no matching cached itinerary, and `flight` is
            absent; retry later, or price live with `POST /v1/flight_search`."
          example: ok
        monitored_at:
          type: string
          example: "2026-06-01T12:34:56Z"
        flight:
          $ref: "#/components/schemas/MonitoredFlight"
        request_echo:
          nullable: true
      required:
        - priced_for
        - status
    PriceMonitoringRequest:
      type: object
      properties:
        origin:
          type: string
          example: PAR
        destination:
          type: string
          example: NYC
        departure_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        return_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        origin_type:
          type: string
          enum: &a18
            - city
            - airport
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
        destination_type:
          type: string
          enum: *a18
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
        cabin_class:
          type: string
          enum: *a15
        direct_only:
          type: boolean
          description: Only direct flights. Cached fares record whether a fare is direct
            but not how many stops it makes, so this is the only stop filter
            here; POST /v1/flight_search takes `max_stops`.
        max_total:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: Caps the cached fare’s total. Cached fares are priced for one
            adult, so this is the cap on one adult’s fare.
        include_carriers:
          type: array
          items:
            type: string
        exclude_carriers:
          type: array
          items:
            type: string
        accuracy:
          type: string
          enum: *a16
          description: How strict the freshness check on cached fares is. `standard`
            (default) returns fares estimated to be at least 80% likely to still
            be available at the cached price; `high` raises that to 95%, so
            fewer fares come back.
        currency:
          type: string
        locale:
          type: string
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - origin
        - destination
        - departure_date
    ScheduleCarrier:
      type: object
      properties:
        code:
          type: string
          example: AF
        name:
          type: string
          example: Air France
    ScheduleEndpoint:
      type: object
      properties:
        airport:
          type: string
          example: BOS
        city_code:
          type: string
          example: BOS
        city_name:
          type: string
          example: Boston
        time_local:
          type: string
          description: "Local date and time at the airport, `YYYY-MM-DDTHH:MM`, with NO
            UTC offset. It is not an instant: it cannot be compared across
            timezones, and parsing it as UTC is wrong by the airport’s offset."
          example: 2026-10-11T18:25
      required:
        - airport
        - time_local
    ScheduleSegment:
      type: object
      properties:
        marketing_carrier:
          type: string
          example: AF
        marketing_carrier_info:
          $ref: "#/components/schemas/ScheduleCarrier"
        operating_carrier:
          type: string
          example: DL
        operating_carrier_info:
          $ref: "#/components/schemas/ScheduleCarrier"
        flight_number:
          type: string
          example: "333"
        cabin_class:
          type: string
          enum: *a15
          description: This segment’s cabin in this trip.
        depart:
          $ref: "#/components/schemas/ScheduleEndpoint"
        arrive:
          $ref: "#/components/schemas/ScheduleEndpoint"
      required:
        - marketing_carrier
        - flight_number
        - depart
        - arrive
    ScheduleSlice:
      type: object
      properties:
        origin:
          type: string
          example: BOS
        destination:
          type: string
          example: NCE
        stops:
          type: integer
          description: Segment count minus one.
          example: 1
        segments:
          type: array
          items:
            $ref: "#/components/schemas/ScheduleSegment"
      required:
        - origin
        - destination
        - stops
        - segments
    ScheduleTrip:
      type: object
      properties:
        trip_type:
          type: string
          enum: *a14
          example: roundtrip
        cabin_class:
          type: string
          enum: *a15
          description: The highest cabin over all segments of the trip.
        validating_carrier:
          type: string
          example: AF
        last_seen:
          type: string
          description: When a fare search last observed this trip (UTC). It is NOT a
            statement that the trip can be booked today.
          example: "2026-09-30T04:12:09Z"
        slices:
          type: array
          items:
            $ref: "#/components/schemas/ScheduleSlice"
          description: One slice for a one-way trip; outbound then inbound for a round trip.
      required:
        - trip_type
        - validating_carrier
        - last_seen
        - slices
    FlightScheduleResponse:
      type: object
      properties:
        trips:
          type: array
          items:
            $ref: "#/components/schemas/ScheduleTrip"
          description: The page of observed trips. Empty when nothing matches.
        total:
          type: integer
          description: Trips matching the whole request across all pages. A lower bound
            when `truncated` is true.
          example: 116
        truncated:
          type: boolean
          description: True when an airport pair held more trips than one catalog read
            covers. Narrow by `cabin_class`, `max_stops` or a single airport to
            see the rest.
        pagination:
          type: object
          properties:
            next_page_token:
              type: string
              description: Send back as `page_token` for the next page; empty on the last
                page. A page may hold fewer trips than `limit` — only an empty
                token ends the result.
          required:
            - next_page_token
      required:
        - trips
        - total
        - truncated
        - pagination
    FlightScheduleRequest:
      type: object
      properties:
        origin:
          type: string
          pattern: ^[A-Za-z]{3}$
          example: BOS
        destination:
          type: string
          pattern: ^[A-Za-z]{3}$
          example: NCE
        origin_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
        destination_type:
          type: string
          enum: *a9
          description: "How to read the code: `city` searches every airport of the city,
            `airport` only that one airport. Omit it and the platform applies
            one rule: a code that names a multi-airport city is searched as the
            city; every other code is searched as the airport. Untyped NYC, LON
            or PAR is the city; untyped JFK, LHR or CDG is the airport; and
            untyped LAX, MIA or LAS — codes a city shares with its main airport
            — is the CITY, so results can land at any airport of that city. If
            the user named the airport, send `airport`; if they named the city,
            omit the field."
        trip_type:
          type: string
          enum: *a14
          description: "`oneway` returns trips observed as one-way offers and takes no
            `return_date`. `roundtrip` returns observed outbound + inbound
            pairings and requires `return_date`."
          example: roundtrip
        departure_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Local departure day of the outbound journey.
          example: "2026-10-11"
        return_date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Local departure day of the inbound journey. Required when
            `trip_type` is `roundtrip`; not accepted when it is `oneway`.
          example: "2026-10-18"
        cabin_class:
          type: string
          enum: *a15
          description: Filters on the trip’s cabin (the highest over its segments). Omit
            for all cabins — unlike flight search there is no economy default.
        max_stops:
          type: integer
          minimum: 0
          maximum: 3
          description: Most stops allowed in EACH direction. Omit for no bound.
          example: 1
        limit:
          type: integer
          minimum: 1
          maximum: 200
          description: Page size. Defaults to 50.
          example: 50
        page_token:
          type: string
          minLength: 1
          description: "`pagination.next_page_token` of the previous page. Send it with
            the same request fields."
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - origin
        - destination
        - trip_type
        - departure_date
      example:
        origin: BOS
        destination: NCE
        trip_type: roundtrip
        departure_date: "2026-10-11"
        return_date: "2026-10-18"
        max_stops: 1
    TripResponseItem:
      type: object
      properties:
        item_id:
          type: string
          example: itm_4b91c2
        kind:
          type: string
          description: 'What the item is: "flight", "hotel", "car" or "ground". Same field
            name as on get_trip and checkout.'
          example: flight
        type:
          type: string
          description: "Deprecated: use `kind` (same value)."
          deprecated: true
          example: flight
        description:
          type: string
          description: A summary of the selected item.
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. The offer handle this
            item was created from, exactly as it was submitted to
            `trip(add_item)`. On a hotel item it is the `htl_…` rate token; on a
            flight item it is the itinerary id. Two caveats when reconciling: on
            a hotel whose occupancy the provider re-shopped, this stays the
            token you SUBMITTED even though the priced rate moved; and a flight
            added twice on the same itinerary with different fares is
            de-duplicated by itinerary, so the echo can name the first fare
            added."
          example: htl_2d67a7441c60e5de
          deprecated: true
        trip_item_token:
          type: string
          description: The handle `trip(add_item)` took, echoed verbatim. On a hotel or
            car item it is the offer’s `trip_item_token` from the search. On a
            flight item it is the itinerary id and the fare joined by a colon,
            absent when the fare half was never resolved (a caller-supplied
            snapshot skips the resolver); read that absence as "the platform
            cannot name the fare", never as a different fare.
          example: of_9c1d2e:FARE_ABC
        hotel_id:
          type: string
          description: The property this hotel item books — the same id `hotel_search`
            publishes, so an item joins straight back to the search result it
            came from. Hotel items only.
          example: lp1f2c3
        special_requests:
          type: array
          items:
            type: string
          description: The special requests submitted with `trip(add_item)` for this hotel
            item, as stored — trimmed, blank entries dropped — and forwarded to
            the hotel supplier at booking. Requests only — the hotel may not
            honour them, and a confirmed booking does not imply it will. Hotel
            items only; absent when none were given (JIN-2499).
        booking_scope:
          type: string
          description: "`room_bundle` means the submitted hotel offer token covers every
            room in `rooms`. Absent on every other hotel item, a single room
            included: read `rooms` for the rooms an item covers, and
            `booking_scope` only to learn whether one token books them all."
          example: room_bundle
        num_rooms:
          type: integer
          minimum: 1
          description: "Number of rooms this hotel item covers: 1 for a single room, the
            bundle size for a room bundle. Hotel items only; absent when the
            platform cannot state the party the item was priced for."
          example: 1
        rooms:
          type: array
          items:
            $ref: "#/components/schemas/HotelBundleRoom"
          description: One entry per room this hotel item covers, single room or bundle
            (JIN-2565). Each entry states in `occupancy` the party that room was
            priced for — adults and children’s ages — so a checkout page can
            show the guest who the rate is for before payment, and a wrong child
            age, which changes the price and the room, is caught before the
            money moves. On a single room the entry’s room, board, refundability
            and tax lines are the item’s own, the same figures `hotel_terms`
            states; on a room bundle each entry carries that room’s details from
            the supplier. The item price remains the authoritative customer
            total for every room together. Absent when the platform holds no
            party for the item.
        price:
          type: number
          description: "Deprecated: use `price_money` instead. Item total as a number in
            major currency units, with currency in the separate `currency`
            field. Absent until pricing is available; absence does not mean
            free."
          example: 545.55
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `price_money` instead. ISO currency code for the
            item price. Absent until pricing is available."
          example: EUR
          deprecated: true
        price_display:
          type: string
          description: "Deprecated: use `price_money` instead. The item price as a string
            ready to show, when X-Money-Display: iso is requested."
          example: EUR 545.55
          deprecated: true
        price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Item total. Absent until pricing is available; absence does not
                mean free.
    TripIdentityDocument:
      type: object
      properties:
        status:
          type: string
          description: "`absent`: none of the document's fields were sent. `saved`:
            stored, and sent to the airline with the flight booking (this does
            not mean the airline accepted it). `invalid`: received, but it
            cannot be sent as is, so the booking goes ahead without it;
            `invalid_fields` names what to correct. More values may be added:
            treat one you do not know as not usable."
          example: saved
        invalid_fields:
          type: array
          items:
            type: string
          description: The missing or failing fields, by their `upsert_travelers` names.
            Sent only when `status` is `invalid`.
          example:
            - passport_expiry
      required:
        - status
    TripTraveler:
      type: object
      properties:
        traveler_ref:
          type: string
          description: "The reference to send as `traveler_ref` when selecting a
            per-traveler ancillary: `pax_<N>`, the traveler's 1-based position
            in `travelers`."
          example: pax_1
        pax_ref_id:
          type: string
          description: "Deprecated: use `traveler_ref` instead. Same value."
          example: pax_1
          deprecated: true
        first_name:
          type: string
          example: John
        last_name:
          type: string
          example: Doe
        date_of_birth:
          type: string
          example: "1990-01-15"
        gender:
          type: string
          example: MALE
        traveler_type:
          type: string
          enum:
            - adult
            - child
            - infant
          example: adult
        passenger_type:
          type: string
          description: "Deprecated: use `traveler_type` instead. The same type in
            uppercase."
          example: ADULT
          deprecated: true
        identity_documents:
          type: object
          properties:
            passport:
              $ref: "#/components/schemas/TripIdentityDocument"
            known_traveler_number:
              $ref: "#/components/schemas/TripIdentityDocument"
            redress_number:
              $ref: "#/components/schemas/TripIdentityDocument"
          required:
            - passport
            - known_traveler_number
            - redress_number
          description: Whether each travel document sent on `upsert_travelers` was saved
            and will be sent with a flight booking. The passport, Known Traveler
            and redress numbers themselves are not returned. `upsert_travelers`
            replaces the whole traveler list, so a document left out of a later
            upsert reads `absent`.
      description: A traveler stored on the trip. A `frequent_flyer` sent on write is
        echoed back alongside these when present; travel documents are reported
        in `identity_documents`, without their values.
    HotelRoomPrimaryGuest:
      type: object
      properties:
        occupancy_number:
          type: integer
          minimum: 1
          description: Stable one-based room slot within the selected room bundle.
          example: 1
        first_name:
          type: string
        last_name:
          type: string
        email:
          type: string
          format: email
      required:
        - occupancy_number
        - first_name
        - last_name
        - email
      additionalProperties: false
    HotelRoomGuests:
      type: object
      additionalProperties:
        type: array
        items:
          $ref: "#/components/schemas/HotelRoomPrimaryGuest"
        minItems: 1
      description: Optional primary adult room-contact overrides keyed by the returned
        hotel item_id/product_id. Each product array is non-empty and
        occupancy_number values are unique positive room slots; omitted slots
        use persisted adult travelers in order with the trip contact email. The
        trip must already exist because the keys refer to its items.
    TripResponse:
      type: object
      properties:
        trip_id:
          type: string
          example: trip_1048576
        status:
          type: string
          enum: &a19
            - draft
            - quoting
            - quoted
            - fulfillment_prepared
            - fulfilling
            - fulfilled
            - partially_fulfilled
            - failed
            - cancelled
            - expired
          description: "Where the trip is in its lifecycle, as one value for the whole
            trip. The booking’s progress after payment is `booking_state` (GET
            /v1/trip/{trip_id}); the four booking values below (`fulfilling`,
            `fulfilled`, `partially_fulfilled`, `failed`) are deprecated in
            favour of it and still sent. `draft`: being built or priced, nothing
            paid. `fulfilling`: payment was submitted and booking started. Then
            exactly one outcome: `fulfilled` (`booking_state` `completed`),
            `partially_fulfilled` (`partial`) or `failed` (`failed`).
            `cancelled`: replaced by a new trip when it was re-shopped.
            `expired` is the 24-hour lapse: it is evaluated LAZILY, on the read
            that first observes it, so this call is where a dead trip becomes
            visible. Once a trip is expired, adding items, setting travelers and
            checkout are refused with `TRIP_EXPIRED`; any other state that
            refuses a write answers `TRIP_STATE_CONFLICT` and names the state
            here. Start a new trip — a lapsed one cannot be revived. `quoting`,
            `quoted` and `fulfillment_prepared` are reserved and not currently
            set; quote progress is in `quote.status`."
          example: draft
        actions_performed:
          type: array
          items:
            type: string
          example:
            - created
            - add_item
        items:
          type: array
          items:
            $ref: "#/components/schemas/TripResponseItem"
        travelers:
          type: array
          items:
            $ref: "#/components/schemas/TripTraveler"
        contact:
          type: object
          properties:
            email:
              type: string
            phone:
              type: string
            title:
              type: string
        hotel_room_guests:
          $ref: "#/components/schemas/HotelRoomGuests"
        totals:
          type: object
          properties:
            currency:
              type: string
              description: "Deprecated: use `total_money` instead. ISO currency code of
                `total`."
              deprecated: true
            total:
              type: number
              description: "Deprecated: use `total_money` instead. The trip total in major
                currency units. Absent on a mixed-currency trip."
              deprecated: true
            total_display:
              type: string
              description: 'Deprecated: use `total_money` instead. The trip total as a string
                ready to show, e.g. "USD 318.40". Absent with `total`.'
              example: USD 318.40
              deprecated: true
            total_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The trip total. Absent when the trip holds items priced in more
                    than one currency, and while nothing is priced.
          example:
            currency: USD
            total: 318.4
      required:
        - trip_id
    TripStateResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - TRIP_EXPIRED
                - TRIP_STATE_CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        status:
          type: string
          enum: *a19
          description: The trip state that refused the write. `expired` on TRIP_EXPIRED;
            on TRIP_STATE_CONFLICT it is whichever state the trip is actually
            in. Nothing was changed, so re-reading the trip returns this same
            state.
          example: expired
      required:
        - error
    FrequentFlyer:
      type: object
      properties:
        airline:
          type: string
          description: IATA code of the loyalty program issuer (e.g. `LH` for Lufthansa
            Miles & More), not necessarily the operating carrier — alliances
            credit miles on partner flights.
          example: LH
        number:
          type: string
          description: Membership / account number for that loyalty program.
          example: "992100100"
      required:
        - airline
        - number
      description: Optional per-passenger frequent-flyer membership so airline miles
        are credited on the booking. Flights only; when present, both airline
        and number are required.
    Traveler:
      type: object
      properties:
        first_name:
          type: string
          description: "For flights, the airline must be able to print the name on the
            ticket: Latin letters (accents allowed), spaces, hyphens and
            apostrophes only. The last name holds at most 29 characters (the
            airline cannot ticket a longer surname), and first, middle and last
            name together at most 63. Two travellers in one trip cannot share
            the same full name. A name that breaks these rules is refused at
            upsert_travelers or checkout with 400 BAD_REQUEST and `error.field`
            naming the traveller."
        last_name:
          type: string
          description: "For flights, the airline must be able to print the name on the
            ticket: Latin letters (accents allowed), spaces, hyphens and
            apostrophes only. The last name holds at most 29 characters (the
            airline cannot ticket a longer surname), and first, middle and last
            name together at most 63. Two travellers in one trip cannot share
            the same full name. A name that breaks these rules is refused at
            upsert_travelers or checkout with 400 BAD_REQUEST and `error.field`
            naming the traveller."
        date_of_birth:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Date of birth (YYYY-MM-DD, nothing before or after it). Required
            for flights, and for a `child` or `infant` staying at a hotel;
            optional for an adult on a hotel-only trip. For flights it cannot be
            in the future and must agree with `traveler_type` on the trip's
            flight dates; otherwise upsert_travelers or checkout answers 400
            BAD_REQUEST with `error.field` naming the traveller and field.
        gender:
          type: string
          enum:
            - MALE
            - FEMALE
          description: Required for flights; optional for hotel-only trips.
        traveler_type:
          type: string
          enum:
            - adult
            - child
            - infant
          description: "For flights, the traveller's age on the date the booking ages
            travellers on decides the type — the trip's first flight, or for
            some bookings the return flight of a round trip: `adult` 12 or
            older, `child` 2 to 11, `infant` under 2, and an `infant` must still
            be under 2 on the trip's last flight. A type the `date_of_birth`
            contradicts is refused at upsert_travelers (once the trip holds the
            flight) or at checkout with 400 BAD_REQUEST and `error.field` naming
            the traveller. A flight searched for another party is re-priced for
            these travellers at checkout, on the same flights and fare family;
            when that fare is not sold for them, checkout answers 409
            `OFFER_UNAVAILABLE`. Each hotel in the trip is booked with these
            travellers (a `room_bundle` hotel whose rooms `hotel_room_guests`
            names is booked for those room guests instead), so they cannot name
            more adults or more children than its rooms were priced for (the
            hotel_search `occupancies`: `adults` and `children_ages`), and each
            child's age at check-in must be one of the priced `children_ages`.
            The hotel counts a traveller by age at check-in, 18 or older being
            an adult, and a traveller with no `date_of_birth` as an adult.
            upsert_travelers or checkout answers 400 BAD_REQUEST naming the
            first traveller over a count or with an age the room was not priced
            for; search the hotel again for the party."
        nationality:
          type: string
        passport_number:
          type: string
        passport_expiry:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Passport expiry (YYYY-MM-DD, nothing before or after it). For
            flights it cannot be before the trip's last flight; otherwise
            upsert_travelers or checkout answers 400 BAD_REQUEST with
            `error.field` naming the traveller.
        passport_country:
          type: string
        frequent_flyer:
          $ref: "#/components/schemas/FrequentFlyer"
        known_traveler_number:
          type: string
          description: US trusted-traveler Known Traveler Number (TSA PreCheck / Global
            Entry). Flights only; sent to the airline as Secure Flight data so
            PreCheck eligibility prints on the boarding pass.
          example: "998765432"
        known_traveler_issuing_country:
          type: string
          description: ISO 3166-1 alpha-2 country that issued the Known Traveler Number.
            Defaults to `US` downstream; ignored without known_traveler_number.
          example: US
        redress_number:
          type: string
          description: DHS redress control number (TRIP program). Flights only; sent to
            the airline as Secure Flight data.
          example: "1234567"
        redress_issuing_country:
          type: string
          description: ISO 3166-1 alpha-2 country that issued the redress number. Defaults
            to `US` downstream; ignored without redress_number.
          example: US
      required:
        - first_name
        - last_name
        - traveler_type
    Contact:
      type: object
      properties:
        email:
          type: string
          format: email
          description: "Contact email for booking confirmations. A trip with a flight
            needs it before payment: without a contact email, checkout answers
            422 `MISSING_CUSTOMER_DETAILS` with `email` in `missing_fields`."
        phone:
          type: string
          description: "Contact phone in international format: a leading `+` and country
            code, e.g. `+12025550147`. Spaces, hyphens, dots and parentheses are
            accepted and removed. A number without the leading `+` is rejected
            with `INVALID_PHONE_NUMBER`. Required to complete a booking."
          example: "+12025550147"
        title:
          type: string
          description: Honorific of the booking contact (e.g. "mr", "ms", "mx"). Free
            text, resolved downstream per provider. Required to book a car
            rental; optional otherwise.
          example: mr
      required:
        - email
        - phone
      description: Booking contact (email + phone, optionally title). Optional while
        building the trip, but required before booking.
    TripRequest:
      type: object
      properties:
        trip_id:
          type: string
        add_item:
          type: object
          properties:
            trip_item_token:
              type: string
            special_requests:
              type: array
              items:
                type: string
                maxLength: 500
              maxItems: 10
              description: "HOTEL ITEMS ONLY. Free-text special requests for the property, one
                per entry — late arrival, quiet room, high floor, bedding
                preference, non-smoking room, baby cot, accessibility needs.
                They apply to the whole stay and are forwarded to the hotel
                supplier with the booking as REQUESTS ONLY: neither Jinko nor
                the supplier guarantees them, and a confirmed booking does not
                mean the hotel will honour them. At most 10 entries of 500
                characters each and 1500 characters in total, counted after
                trimming; blank entries are dropped. Ignored on flight and
                ground items. Echoed back on the item as `special_requests`,
                trimmed and without the blank entries (JIN-2499)."
              example:
                - Expected arrival around 11:30 PM.
                - A quiet room on a high floor, if available.
          required:
            - trip_item_token
        remove_item:
          type: object
          properties:
            item_id:
              type: string
          required:
            - item_id
        upsert_travelers:
          type: object
          properties:
            travelers:
              type: array
              items:
                $ref: "#/components/schemas/Traveler"
              description: Travelers on the trip (replaces all). Required to complete a
                booking; the first traveler also supplies the booking contact
                name.
            contact:
              $ref: "#/components/schemas/Contact"
          required:
            - travelers
        hotel_room_guests:
          $ref: "#/components/schemas/HotelRoomGuests"
        intent:
          $ref: "#/components/schemas/IntentInput"
      example:
        trip_id: trip_1048576
        add_item:
          trip_item_token: htl_2d67a7441c60e5de
          special_requests:
            - Expected arrival around 11:30 PM.
            - A quiet room on a high floor, if available.
    PaymentAttemptOutcome:
      type: object
      properties:
        payment_attempt_id:
          type: string
        trip_id:
          type: string
          description: The trip this attempt pays, written with a `trip_` prefix
            (`trip_1048576`); the trip answers carry the same id without it
            (`1048576`). Strip the prefix to compare the two.
          example: trip_1048576
        quote_id:
          type: string
          description: The quote this payment is taken against.
          example: "2097152"
        quoted_cart_id:
          type: integer
          description: "Deprecated: use `quote_id` instead. The same quote as an integer."
          deprecated: true
        fulfillment_cart_id:
          type: integer
          description: "Deprecated: use `booking_ref` instead. An internal number for the
            booking this payment funds."
          deprecated: true
        payment_status:
          type: string
          enum:
            - not_started
            - pending
            - requires_authentication
            - authorized
            - captured
            - declined
            - cancelling
            - cancelled
            - expired
            - failed
        booking_status:
          type: string
          description: The detailed status of the booking this payment started,
            `not_scheduled` until booking begins. `booking_state` on GET
            /v1/trip/{trip_id} is its summary.
        failure_reason:
          type: string
          nullable: true
          description: "Why the booking failed, when it failed after payment and the cause
            is known: `offer_unavailable`, `price_changed`,
            `booking_not_created` (the supplier holds no booking; nothing was
            booked and no money was taken), `booking_cancelled_at_provider`,
            `ticketing_refused`. Null otherwise. For `offer_unavailable`, the
            supplier no longer sells the priced offer. Nothing was booked and
            the card authorisation was released. Search again and book a new
            offer. The `booking.failed` webhook carries the same reason with a
            sentence to show the traveller (`failure_message`)."
          example: booking_not_created
        items:
          type: array
          items:
            type: object
            properties:
              booked_item_id:
                type: string
                description: The booked item, as get_booking and the servicing routes name it.
                  Absent only when the item cannot be named yet.
                example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
              item_id:
                type: integer
                description: "Deprecated: use `booked_item_id` instead. The booked item as an
                  integer."
                deprecated: true
              outcome:
                type: string
              failure_reason:
                type: string
                nullable: true
                description: "Why the booking failed, when it failed after payment and the cause
                  is known: `offer_unavailable`, `price_changed`,
                  `booking_not_created` (the supplier holds no booking; nothing
                  was booked and no money was taken),
                  `booking_cancelled_at_provider`, `ticketing_refused`. Null
                  otherwise. For `offer_unavailable`, the supplier no longer
                  sells the priced offer. Nothing was booked and the card
                  authorisation was released. Search again and book a new offer.
                  The `booking.failed` webhook carries the same reason with a
                  sentence to show the traveller (`failure_message`)."
                example: booking_not_created
            required:
              - item_id
              - outcome
        booking_ref:
          type: string
          description: The booking reference. Absent until the booking has one; never null.
        payment_error:
          type: object
          nullable: true
          properties:
            code:
              type: string
              enum: &a20
                - CREDENTIAL_FORMAT_INVALID
                - PAYMENT_TYPE_NOT_ENABLED
                - PAYMENT_CREDENTIAL_INVALID
                - TRIP_OWNED_BY_OTHER_PAYMENT
                - IDEMPOTENCY_KEY_REUSED
                - ATTEMPT_IN_PROGRESS
                - CARD_DECLINED
                - CARD_ALIAS_EXPIRED
                - PAYMENT_CREDENTIAL_REJECTED
                - AUTHENTICATION_REQUIRED
                - AUTHENTICATION_FAILED
                - AUTHENTICATION_ABANDONED
                - QUOTE_EXPIRED
                - ATTEMPT_TERMINAL
                - PAYMENT_OUTCOME_UNKNOWN
                - FULFILLMENT_DISPATCH_DELAYED
                - RECONCILIATION_REQUIRED
                - TEMPORARILY_UNAVAILABLE
            message:
              type: string
          required:
            - code
            - message
          description: "Why the payment has not gone through, or null. On the
            `checkout_url` payment page, a card the issuer declines
            (`card_declined`) or whose authentication fails
            (`authentication_failed`) is reported here while `payment_status`
            stays `pending` and `recovery.action` is `poll`: the payer can use
            another card on the same page until the quote expires. It returns to
            null when a card is authorized. `CARD_ALIAS_EXPIRED`: The card alias
            expired before the booking was dispatched. Follow `recovery.action`;
            when it is `retry_new_key`: Submit the card again on the pay
            hostname with a new Idempotency-Key."
        recovery:
          type: object
          properties:
            action:
              type: string
              enum: &a21
                - poll
                - authenticate
                - retry_same_key
                - retry_new_key
                - recheckout
                - contact_support
                - stop
              description: "The next step. `authenticate`: when `authentication` is present,
                open `authentication.url` before `authentication.expires_at`.
                For a Shared Payment Token (`spt`), first read the token's
                `next_action.use_stripe_sdk.value` with your own Stripe secret
                key and append it unchanged: open `authentication.url + \"#hv=\"
                + <value>`, or call `stripe.handleNextAction({ hashedValue })`
                with Stripe.js on your own page. Then poll `GET
                /v1/trip/{trip_id}/payment_attempts/{payment_attempt_id}` until
                `payment_status` is none of `requires_authentication`,
                `cancelling` or `pending`."
            replacement_credential_required:
              type: boolean
          required:
            - action
            - replacement_credential_required
        recovery_status:
          type: string
          enum:
            - automatic
            - manual_review
        quote_expires_at:
          type: string
          format: date-time
        retry_after_seconds:
          type: integer
          description: Seconds to wait before reading the payment attempt again. Present
            only while `recovery.action` is `poll`; absent otherwise, never
            null.
        authentication:
          type: object
          properties:
            url:
              type: string
            expires_at:
              type: string
              format: date-time
          required:
            - url
            - expires_at
          description: "Where the customer authenticates when `recovery.action` is
            `authenticate`: open `url` before `expires_at`. For a Shared Payment
            Token (`spt`), `url` is a Jinko-hosted page that needs the token's
            hashed value: read the issued token's
            `next_action.use_stripe_sdk.value` with your own Stripe secret key
            and open `url + \"#hv=\" + <value>`, passing the value unchanged.
            The value travels in the URL fragment, which keeps it out of server
            logs."
        money:
          type: object
          properties:
            authorized:
              $ref: "#/components/schemas/Money"
            captured:
              $ref: "#/components/schemas/Money"
            released:
              $ref: "#/components/schemas/Money"
            refunded:
              $ref: "#/components/schemas/Money"
            externally_reimbursed:
              $ref: "#/components/schemas/Money"
            resolution_status:
              type: string
              enum:
                - pending
                - resolved
                - manual_review
                - external_reimbursement_pending
                - externally_reimbursed
            refund_reference:
              type: string
      required:
        - payment_attempt_id
        - trip_id
        - quote_id
        - quoted_cart_id
        - payment_status
        - booking_status
        - payment_error
        - recovery
        - recovery_status
    AncillarySeat:
      type: object
      properties:
        seat_number:
          type: string
          example: 14A
        available:
          type: boolean
        chargeable:
          type: boolean
          description: True when the seat has a price.
        price:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `price_money` instead. The seat price in major
                units in the trip currency."
              deprecated: true
        price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The exact seat price in the trip currency. Absent for a free seat.
        characteristics:
          type: array
          items:
            type: string
          example:
            - WINDOW
      description: A numbered seat. Read `price_money` for its exact price in the trip
        currency. Both price fields are absent for a free seat.
    AncillarySeatMap:
      type: object
      properties:
        segment_ref_id:
          type: string
          example: seg_1
        flight_number:
          type: string
          example: W62202
        seats:
          type: array
          items:
            $ref: "#/components/schemas/AncillarySeat"
      description: The numbered seats for the segment covered by a seat offer. Select
        a seat with `available` true; its `price_money`, when present, is exact
        money in the trip currency.
    AncillaryOffer:
      type: object
      properties:
        offer_id:
          type: string
          description: Opaque identifier of this ancillary offer. Pass it back exactly as
            received in `selections[].offer_id`; do not parse or build it.
          example: anc_3f9a1c27e4b8d051
        type:
          type: string
          description: 'Ancillary family — "bag", "seat", "meal", "assistance", … An open
            set. Offers with type "seat" carry `seat_map` and no
            `price_per_unit`: the price is per seat, in
            `seat_map.seats[].price_money`.'
          example: bag
        label:
          type: string
          description: The provider label verbatim, kept as the source of truth. Some
            labels arrive with HTML entities and "&" component-joiners — show
            `display_label` instead.
          example: bag&1 x large 55 x 40 x 20 cm&Includes Speedy Boarding
        display_label:
          type: string
          description: 'Human-readable rendering of `label`: HTML entities decoded, "&"
            joiners normalised to ", ". This is the one to display.'
          example: bag, 1 x large 55 x 40 x 20 cm, Includes Speedy Boarding
        description:
          type: string
        price_per_unit:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `price_per_unit_money` instead. The unit price in
                MAJOR currency units."
              deprecated: true
        price_per_unit_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The price of one unit of this ancillary. Absent when the offer
                carries no price, and on seat offers, which price each seat in
                the seat map.
        scope:
          type: string
          description: "Seat offers only: one seat per passenger per segment."
          example: PER_PAX_PER_SEGMENT
        segment_ref_ids:
          type: array
          items:
            type: string
          description: The segment(s) a seat offer covers, one per offer. Pass the one
            entry back as the selection's `segment_ref_ids`.
          example:
            - seg_1
        seat_map:
          $ref: "#/components/schemas/AncillarySeatMap"
        seat_map_status:
          type: string
          enum:
            - pending
            - ready
          description: "Seat offers only: pending means the seat map is still loading and
            seat_map.seats is empty; read again. Ready means seats are listed."
        per_pax:
          type: boolean
          description: True when the price is charged per passenger rather than once per
            booking.
          example: true
        max_quantity:
          type: integer
          example: 2
        paid_at:
          type: string
          enum:
            - now
            - local
          description: "Car rate extras only. `now`: charged by Jinko at checkout and
            inside the item price once selected. `local`: collected by the
            rental desk on pick-up — selectable, but never part of the charge.
            Absent for flight ancillaries, which are always charged by Jinko."
          example: now
      required:
        - offer_id
    SelectedAncillary:
      type: object
      properties:
        offer_id:
          type: string
          description: Opaque identifier of this ancillary offer. Pass it back exactly as
            received in `selections[].offer_id`; do not parse or build it.
          example: anc_3f9a1c27e4b8d051
        traveler_ref:
          type: string
          description: The traveler the selection applies to; absent on a booking-level
            ancillary.
          example: pax_1
        pax_ref_id:
          type: string
          description: "Deprecated: use `traveler_ref` instead. Same value."
          example: pax_1
          deprecated: true
        quantity:
          type: integer
          example: 1
        type:
          type: string
          description: Ancillary family on a booked outcome, e.g. "seat" or "bag"
            (lowercase, open set). May be absent before booking.
          example: seat
        seat_number:
          type: string
          example: 14A
        segment_ref_ids:
          type: array
          items:
            type: string
          example:
            - seg_1
        price:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `price_money` instead. The unit price of the
                chosen seat, set by the server: major units in the trip
                currency. Absent for a free seat or a selection without its own
                unit price."
              deprecated: true
        price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The exact unit price of the chosen seat, set by the server. Absent
                for a free seat or a selection without its own unit price, e.g.
                a bag.
        status:
          type: string
          enum:
            - pending
            - confirmed
            - failed
          description: Absent before booking. For seats, `pending` means the airline has
            not confirmed the seat yet. `confirmed` means booked with the
            airline. `failed` means not booked.
        not_charged:
          type: boolean
          description: true when this seat is not charged to the traveler.
        failure_reason:
          type: string
          description: Why an ancillary failed, or why a pending airline outcome needs
            reconciliation.
      required:
        - offer_id
      description: An ancillary selected on a trip item, as the trip read and the
        select_ancillaries response both return it. Provider data is never
        included.
    PriceChange:
      type: object
      properties:
        original:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `original_money` instead. The selling price shown
                at search time, before the quote, in MAJOR currency units."
              deprecated: true
        current:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `current_money` instead. The selling price the
                trip is quoted at — the same figure as `price` — in MAJOR
                currency units."
              deprecated: true
        delta:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `delta_money` instead. `current` minus `original`,
                SIGNED, in MAJOR currency units: positive when the price rose,
                negative when it fell."
              deprecated: true
        original_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The selling price shown at search time, before the quote.
        current_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The selling price the trip is quoted at — the same figure as
                `price_money`.
        delta_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "`current_money` minus `original_money`, SIGNED: `value` is
                positive when the price rose, negative when it fell."
      required:
        - original
        - current
        - delta
      description: The move between the price shown at search time and the price the
        trip is quoted at, stated as three figures so the caller can report it
        without subtracting. Read `original_money`, `current_money` and
        `delta_money`; the deprecated `original`, `current` and `delta` carry
        the same figures in major currency units. All are in one currency,
        matching the item’s price. Present ONLY when the two differ — an item
        whose price held carries no `price_change` at all, and `price_changed`
        is true whenever it is present.
    HotelTerms:
      type: object
      properties:
        terms_as_of:
          type: string
          enum:
            - search
            - quote
          description: How fresh these terms are. `search` — captured in the search
            snapshot the item was created from and held since. `quote` — re-read
            from the provider when the trip was quoted. Today the platform
            always answers `search`.
          example: search
        taxes_breakdown:
          type: array
          items:
            $ref: "#/components/schemas/TaxLine"
          description: Taxes and fees on the held rate. An empty array means no tax is
            known, not that there is none; check `included` per line before
            adding anything to the item price.
        cancellation_schedule:
          type: array
          items:
            $ref: "#/components/schemas/CancellationStep"
          description: The penalty ladder for this rate, chronological. Absent when the
            provider published none — which is not a statement that cancelling
            is free.
        free_cancellation_until:
          type: string
          description: Last instant the stay can be cancelled at no charge. RFC 3339 with
            the supplier’s declared UTC offset. Absent when the supplier
            declared no timezone — the platform never invents an offset, so a
            deadline it cannot place on the clock is withheld rather than
            published ambiguously — and absent when the rate is non-refundable
            or the provider named no deadline.
          example: "2026-08-18T10:00:00+02:00"
        is_refundable:
          type: boolean
          example: false
        board_type:
          type: string
          example: RO
        board_name:
          type: string
          example: Room Only
        payment_types:
          type: array
          items:
            $ref: "#/components/schemas/HotelPaymentType"
          description: How the rate can be settled. Each value appears at most once.
          example: *a8
        room_name:
          type: string
          example: Superior Double
        room_capacity:
          type: integer
          example: 2
      description: "The rate terms behind a hotel item — cancellation ladder, taxes,
        board and room — as the platform holds them. They were captured at
        SEARCH time and are not re-confirmed at quote: read `terms_as_of` before
        treating any of them as a guarantee of what the provider will charge at
        booking. Present on hotel items only."
    TripItem:
      type: object
      properties:
        item_id:
          type: string
          example: itm_4b91c2
        kind:
          type: string
          description: 'What the item is: "flight", "hotel", "car" or "ground".'
          example: flight
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. The offer handle this
            item was created from, exactly as it was submitted to
            `trip(add_item)`. On a hotel item it is the `htl_…` rate token; on a
            flight item it is the itinerary id. Two caveats when reconciling: on
            a hotel whose occupancy the provider re-shopped, this stays the
            token you SUBMITTED even though the priced rate moved; and a flight
            added twice on the same itinerary with different fares is
            de-duplicated by itinerary, so the echo can name the first fare
            added."
          example: htl_2d67a7441c60e5de
          deprecated: true
        trip_item_token:
          type: string
          description: The handle `trip(add_item)` took, echoed verbatim. On a hotel or
            car item it is the offer’s `trip_item_token` from the search. On a
            flight item it is the itinerary id and the fare joined by a colon,
            absent when the fare half was never resolved (a caller-supplied
            snapshot skips the resolver); read that absence as "the platform
            cannot name the fare", never as a different fare.
          example: of_9c1d2e:FARE_ABC
        hotel_id:
          type: string
          description: The property this hotel item books — the same id `hotel_search`
            publishes, so an item joins straight back to the search result it
            came from. Hotel items only.
          example: lp1f2c3
        special_requests:
          type: array
          items:
            type: string
          description: The special requests submitted with `trip(add_item)` for this hotel
            item, as stored — trimmed, blank entries dropped — and forwarded to
            the hotel supplier at booking. Requests only — the hotel may not
            honour them, and a confirmed booking does not imply it will. Hotel
            items only; absent when none were given (JIN-2499).
        booking_scope:
          type: string
          description: "`room_bundle` means the submitted hotel offer token covers every
            room in `rooms`. Absent on every other hotel item, a single room
            included: read `rooms` for the rooms an item covers, and
            `booking_scope` only to learn whether one token books them all."
          example: room_bundle
        num_rooms:
          type: integer
          minimum: 1
          description: "Number of rooms this hotel item covers: 1 for a single room, the
            bundle size for a room bundle. Hotel items only; absent when the
            platform cannot state the party the item was priced for."
          example: 1
        rooms:
          type: array
          items:
            $ref: "#/components/schemas/HotelBundleRoom"
          description: One entry per room this hotel item covers, single room or bundle
            (JIN-2565). Each entry states in `occupancy` the party that room was
            priced for — adults and children’s ages — so a checkout page can
            show the guest who the rate is for before payment, and a wrong child
            age, which changes the price and the room, is caught before the
            money moves. On a single room the entry’s room, board, refundability
            and tax lines are the item’s own, the same figures `hotel_terms`
            states; on a room bundle each entry carries that room’s details from
            the supplier. The item price remains the authoritative customer
            total for every room together. Absent when the platform holds no
            party for the item.
        price:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `price_money` instead. Item total in major
                currency units. Absent until the trip has been quoted."
              deprecated: true
        price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Item total. Absent until the trip has been quoted — an unpriced
                item carries no `price_money` key at all, so absence means "not
                priced yet", not "free".
        pax_count:
          type: number
          example: 1
        available_ancillaries:
          type: array
          items:
            $ref: "#/components/schemas/AncillaryOffer"
          description: Ancillaries that can still be selected on this item. Empty once
            nothing is on offer; populated only after the item has been quoted.
        selected_ancillaries:
          type: array
          items:
            $ref: "#/components/schemas/SelectedAncillary"
          description: Ancillaries already selected on this item.
        price_changed:
          type: boolean
          description: True when the provider re-priced this item between the search
            snapshot and the live quote. Checkout PROCEEDS at the new `price` —
            show the change before taking payment. Read `price_change` for the
            two figures and the signed difference. Absent when the price held.
          example: true
        original_price:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `original_price_money` instead. The snapshot price
                recorded at search time, in major currency units."
              deprecated: true
        original_price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The snapshot price recorded at search time. Present only when
                `price_changed` is true; compare it against `price_money` to
                show the caller what moved.
        price_change:
          $ref: "#/components/schemas/PriceChange"
        required_attributes:
          type: object
          properties:
            source:
              type: string
              description: 'Origin of the requirement. Known values: "provider"
                (carrier-stated, authoritative) and "derived" (inferred from the
                itinerary; advisory only, not a compliance statement). The value
                is passed through without additional validation, so new sources
                may appear.'
              example: provider
            per_passenger:
              type: array
              items:
                type: string
              description: Attribute names that must be collected for each passenger. Names
                are an open set in the provider’s own vocabulary.
              example:
                - PassportNumber
                - PassportExpiryDate
                - DateOfBirth
            booking:
              type: array
              items:
                type: string
              description: Attribute names that must be collected once per booking.
              example:
                - BillingAddress
                - PostCode
            per_passenger_conditional:
              type: array
              items:
                type: string
              description: Attribute names that may be required for each passenger depending
                on carrier, route, or passenger details. Collect them when in
                doubt.
              example:
                - Nationality
            booking_conditional:
              type: array
              items:
                type: string
              description: Attribute names that may be required once per booking depending on
                carrier, route, or passenger details. Collect them when in
                doubt.
          description: Extra attributes the carrier requires collected before booking this
            item — e.g. passport fields on carriers that mandate travel
            documents. Contents are passed through without additional
            validation. When this object is absent, no requirement is known;
            absence is NOT a statement that no document is needed.
        hotel_terms:
          $ref: "#/components/schemas/HotelTerms"
    BookingRef:
      type: object
      properties:
        item_id:
          type: string
          example: itm_4b91c2
        kind:
          type: string
          example: flight
        supplier_references:
          type: array
          items:
            $ref: "#/components/schemas/SupplierReference"
          description: "The confirmations the supplier itself issued for this item: one
            per airline record locator, the hotel’s confirmation number, the
            rental company’s confirmation. Empty when none is known yet. The
            traveler quotes these to the airline, hotel or rental desk; `POST
            /v1/get_booking` takes the trip-level `booking_ref`."
        booking_reference:
          type: string
          description: "Deprecated: use `supplier_references` instead. A confirmation
            reference for this item; when the airline’s own locator is not known
            it can hold an id only Jinko’s intermediary answers to."
          example: 8Q69NYQTT
          deprecated: true
        pnr:
          type: string
          description: "Deprecated: use `supplier_references` instead. The same value as
            `booking_reference`."
          example: XM9L2K
          deprecated: true
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. The offer handle this
            item was created from, exactly as it was submitted to
            `trip(add_item)`. On a hotel item it is the `htl_…` rate token; on a
            flight item it is the itinerary id. Two caveats when reconciling: on
            a hotel whose occupancy the provider re-shopped, this stays the
            token you SUBMITTED even though the priced rate moved; and a flight
            added twice on the same itinerary with different fares is
            de-duplicated by itinerary, so the echo can name the first fare
            added."
          example: htl_2d67a7441c60e5de
          deprecated: true
        trip_item_token:
          type: string
          description: The handle `trip(add_item)` took, echoed verbatim. On a hotel or
            car item it is the offer’s `trip_item_token` from the search. On a
            flight item it is the itinerary id and the fare joined by a colon,
            absent when the fare half was never resolved (a caller-supplied
            snapshot skips the resolver); read that absence as "the platform
            cannot name the fare", never as a different fare.
          example: of_9c1d2e:FARE_ABC
        hotel_id:
          type: string
          description: The property this hotel item books — the same id `hotel_search`
            publishes, so an item joins straight back to the search result it
            came from. Hotel items only.
          example: lp1f2c3
        special_requests:
          type: array
          items:
            type: string
          description: The special requests submitted with `trip(add_item)` for this hotel
            item, as stored — trimmed, blank entries dropped — and forwarded to
            the hotel supplier at booking. Requests only — the hotel may not
            honour them, and a confirmed booking does not imply it will. Hotel
            items only; absent when none were given (JIN-2499).
    GetTripResponse:
      type: object
      properties:
        seat_map_url:
          type: string
          description: Link to a page where the traveller picks seats on a visual seat
            map. Present only when a flight item has a seat-map session.
            Expires; read the trip again for a fresh link.
        payment_attempt:
          $ref: "#/components/schemas/PaymentAttemptOutcome"
        trip_id:
          type: string
          example: trip_1048576
        status:
          type: string
          enum: *a19
          description: "Where the trip is in its lifecycle, as one value for the whole
            trip. The booking’s progress after payment is `booking_state` (GET
            /v1/trip/{trip_id}); the four booking values below (`fulfilling`,
            `fulfilled`, `partially_fulfilled`, `failed`) are deprecated in
            favour of it and still sent. `draft`: being built or priced, nothing
            paid. `fulfilling`: payment was submitted and booking started. Then
            exactly one outcome: `fulfilled` (`booking_state` `completed`),
            `partially_fulfilled` (`partial`) or `failed` (`failed`).
            `cancelled`: replaced by a new trip when it was re-shopped.
            `expired` is the 24-hour lapse: it is evaluated LAZILY, on the read
            that first observes it, so this call is where a dead trip becomes
            visible. Once a trip is expired, adding items, setting travelers and
            checkout are refused with `TRIP_EXPIRED`; any other state that
            refuses a write answers `TRIP_STATE_CONFLICT` and names the state
            here. Start a new trip — a lapsed one cannot be revived. `quoting`,
            `quoted` and `fulfillment_prepared` are reserved and not currently
            set; quote progress is in `quote.status`."
          example: draft
        travelers:
          type: array
          items:
            $ref: "#/components/schemas/TripTraveler"
        contact:
          type: object
          properties:
            email:
              type: string
            phone:
              type: string
            title:
              type: string
        hotel_room_guests:
          $ref: "#/components/schemas/HotelRoomGuests"
        items:
          type: array
          items:
            $ref: "#/components/schemas/TripItem"
        total_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `total_amount_money` instead. The trip total in
                major currency units."
              deprecated: true
        total_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The trip total. Absent until the trip has been quoted.
        quote:
          type: object
          properties:
            quote_id:
              type: string
              description: "The quote’s id: pass it as `quote_id` to the typed agent payment,
                or to the MCP `submit_agent_payment`, to pay exactly this
                quote."
              example: "2097152"
            quoted_cart_id:
              type: number
              description: "Deprecated: use `quote_id` instead. The same quote as an integer."
              deprecated: true
            status:
              type: string
            expires_at:
              type: string
              description: The payment deadline of a successfully priced quote. Absent on a
                failed quote; a failed pricing attempt does not establish a
                payable price.
            failure_reason:
              type: string
              enum:
                - offer_expired
                - offer_unavailable
                - provider_error
              description: "Known reason pricing failed. Present only on a failed quote with a
                classified failure. For offer_expired or offer_unavailable,
                search again and replace the unavailable item before checkout.
                provider_error is an upstream technical pricing failure: retry
                checkout once; if it still fails, choose another flight or
                contact support. offer_expired describes a search offer that
                could not be priced, not an established quote expiring."
            failure_message:
              type: string
              description: Safe explanation of a failed pricing attempt, when available. Use
                failure_reason for programmatic handling; the wording can
                change. Where the explanation would carry the supplier’s own
                words, it reads “The booking could not be completed. Contact
                Jinko support.”
            invalid_reason:
              type: string
              description: "Present when the latest priced quote can no longer be paid. Known
                value: `travelers_changed`, the trip's travelers changed after
                it was priced. Treat any other value the same way: the quote is
                not payable. Absent otherwise, including when the quote simply
                passed its `expires_at`. Payment against this quote is refused
                with **410 `QUOTE_EXPIRED`** (`reason: travelers_changed`); call
                `POST /v1/checkout` again to re-quote."
          description: Latest pricing attempt. POST /v1/trip does not start pricing; POST
            /v1/checkout starts it and waits for success or failure. Reading the
            trip does not trigger pricing. A failed quote has no payable price.
          example:
            quote_id: "2097152"
            status: quoted
            expires_at: "2026-06-01T13:04:56Z"
        fulfillment:
          type: object
          properties:
            fulfillment_cart_id:
              type: number
              description: "Deprecated: use `booking_ref` instead. An internal number for the
                booking."
              deprecated: true
            status:
              type: string
              description: "Progress of the booking that started when payment was submitted,
                in detail; `booking_state` is its summary. `awaiting_payment`:
                waiting for the payment to be confirmed. `processing`: booking
                with the suppliers. Outcomes: `completed` (every item booked;
                trip `fulfilled`), `partial` (some items booked; trip
                `partially_fulfilled`), `failed` (nothing booked; trip
                `failed`), `cancelled`. `needs_review`: held for a person to
                resolve; not final. Other known values: pending, preparing,
                prepared, confirming, exchange_partial_failure, expired_quote.
                Additional values may appear."
            phase:
              type: string
            failure_reason:
              type: string
              description: Classified reason for a failed fulfillment, when available.
              example: price_changed
            scheduled_at:
              type: string
              format: date-time
              description: Scheduled fulfillment time (RFC 3339), when available.
              example: "2026-06-01T12:35:00Z"
        booking_state:
          type: string
          enum: &a25
            - awaiting_payment
            - processing
            - completed
            - partial
            - failed
            - cancelled
            - needs_review
          description: "The booking’s progress once payment has started; absent before.
            `awaiting_payment`: waiting for the payment to be confirmed.
            `processing`: booking with the suppliers. Then one outcome:
            `completed` (every item booked), `partial` (some items booked),
            `failed` (nothing booked) or `cancelled`. `needs_review`: held for a
            person at Jinko to resolve; not final. `fulfillment.status` keeps
            the detailed status behind it."
          example: processing
        booking_ref:
          type: string
          description: "The Jinko booking reference for this trip — the value `POST
            /v1/get_booking`, cancel, refund and exchange take as `booking_ref`,
            and the `booking_ref` every webhook event carries. Present as soon
            as booking has been scheduled for the trip, which can be before
            payment completes (a hosted checkout still in progress, or an agent
            submit that fell back to `checkout_url`, leaves the booking
            `awaiting_payment`). Presence does not mean paid: read
            `booking_state`. The value never changes afterwards. One per trip."
          example: JNK-XEVGW5
        bookings:
          type: array
          items:
            $ref: "#/components/schemas/BookingRef"
          description: One entry per item with a booking reference, including items whose
            booking was attempted and failed. The supplier confirmation can be
            empty on failed items; the Jinko reference is the trip-level
            `booking_ref`.
        created_at:
          type: string
          example: "2026-06-01T12:30:00Z"
        updated_at:
          type: string
          example: "2026-06-01T12:34:56Z"
      required:
        - trip_id
    TripAncillariesResponse:
      type: object
      properties:
        trip_id:
          type: string
        status:
          type: string
          example: ready
        quote_id:
          type: string
          example: "2097152"
        quoted_cart_id:
          type: number
          description: "Deprecated: use `quote_id` instead. The same quote as an integer."
          deprecated: true
        expires_at:
          type: string
        retry_after_seconds:
          type: integer
        items:
          type: array
          items:
            $ref: "#/components/schemas/TripItem"
      required:
        - trip_id
        - status
    AncillaryResponse:
      type: object
      properties:
        trip_id:
          type: string
          example: trip_1048576
        item_id:
          type: string
          description: The trip item the selection applied to — `items[].item_id` on the
            trip.
          example: itm_4b91c2
        quoted_item_id:
          type: number
          description: "Deprecated: use `item_id` instead. An internal number for the
            priced item."
          example: 8810231
          deprecated: true
        selected_ancillaries:
          type: array
          items:
            $ref: "#/components/schemas/SelectedAncillary"
        total_with_ancillaries:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: 'The item total including the selected ancillaries, in minor units:
                `amount` is an integer to divide by 10 ** `decimal_places` (e.g.
                `{amount: 23959, currency: "EUR", decimal_places: 2}` is EUR
                239.59). `display` is the same figure to show.'
    AncillaryRequest:
      type: object
      properties:
        trip_id:
          type: string
        item_id:
          type: string
        selections:
          type: array
          items:
            type: object
            properties:
              offer_id:
                type: string
                description: The `offer_id` of an offer in the item’s `available_ancillaries`,
                  exactly as received.
              category:
                type: string
                description: The server resolves the category from the offer.
              traveler_ref:
                type: string
                description: Use the traveler's `traveler_ref` from GET /v1/trip.
              segment_ref_ids:
                type: array
                items:
                  type: string
                description: For a seat, pass the offer's one `segment_ref_id`.
              seat_number:
                type: string
                description: The seat to assign, required when the offer is a seat offer. Pick
                  one from the offer's `seat_map.seats` with `available` true.
                  One seat per passenger per segment, and each seat to at most
                  one passenger.
                example: 14A
              journey_ref_id:
                type: string
              quantity:
                type: number
            required:
              - offer_id
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - trip_id
        - item_id
        - selections
      example:
        trip_id: trip_1048576
        item_id: itm_4b91c2
        selections:
          - offer_id: anc_3f9a1c27e4b8d051
            traveler_ref: pax_1
            quantity: 1
          - offer_id: anc_9b04e7d2c6a1f835
            traveler_ref: pax_1
            segment_ref_ids:
              - seg_1
            seat_number: 14A
    AgentSPTParams:
      type: object
      properties:
        max_amount:
          type: integer
          description: "Deprecated: use `max_amount_money` instead. Locked trip total in
            the smallest currency unit — scope the Shared Payment Token to at
            most this."
          example: 259449
          deprecated: true
        currency:
          type: string
          description: "Deprecated: use `max_amount_money` instead. The trip currency:
            `USD` or `EUR`, depending on the partner's Stripe account binding.
            `agent_spt_params` is present only when the partner accepts SPT for
            this cart currency."
          example: USD
          deprecated: true
        max_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Locked trip total — scope the Shared Payment Token to at most
                `value` (minor units) in `currency`, the trip currency (`USD` or
                `EUR`, depending on the partner's Stripe account binding).
        stripe_profile:
          type: string
          description: Stripe Agentic Commerce network_business_profile id the SPT is
            granted against. Empty until the preview account is provisioned.
        expires_at:
          type: string
          description: "When the quote these params are scoped to expires (RFC 3339) — the
            same instant as `expires_at` on the checkout response. Submitting a
            Shared Payment Token after it answers **410 `QUOTE_EXPIRED`** and
            redeems nothing; call `POST /v1/checkout` again and mint a fresh
            token against the new params. The quote can also be refused earlier
            if the trip's travelers change after pricing (`reason:
            travelers_changed`)."
          example: "2026-06-10T13:04:56Z"
      required:
        - max_amount
        - currency
      description: "Parameters to scope a Shared Payment Token to, so an agent can pay
        programmatically instead of opening `checkout_url`: mint the token
        against these, then call POST /v1/agent_payment/submit with `trip_id`
        and the token. The currency is the trip currency: `USD` or `EUR`,
        depending on the partner's Stripe account binding. **Absent when the
        partner does not accept SPT for this trip currency**; use the returned
        `accepted_payment_types` to select an available payment method, or pay
        through `checkout_url`. The human checkout path ignores this object."
    CheckoutResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: The quote this checkout priced. Pass it as `quote_id` to the typed
            agent payment, or to the MCP `submit_agent_payment`, to pay exactly
            this quote.
          example: "2097152"
        quoted_cart_id:
          type: integer
          description: "Deprecated: use `quote_id` instead. The same quote as an integer."
          deprecated: true
        accepted_payment_types:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - spt
              requires:
                type: object
                properties:
                  headers:
                    type: array
                    items:
                      type: string
                  fields:
                    type: array
                    items:
                      type: string
                required:
                  - headers
                  - fields
              authentication:
                type: string
                enum:
                  - customer_handoff
                  - unavailable
            required:
              - type
              - requires
              - authentication
        session_id:
          type: string
          description: The hosted payment page session behind `checkout_url`. Nothing on
            this API takes it; send the traveler to `checkout_url`.
          example: cs_1048576
        checkout_url:
          type: string
          example: https://app.gojinko.com/checkout?t=<signed token>
        status:
          type: string
          description: Checkout state — "ready", "pending" or "failed".
          example: ready
        expires_at:
          type: string
          description: "When the quote behind this checkout stops being payable (RFC
            3339). At most one hour from the call, and earlier when an offer in
            the trip carries a shorter deadline of its own (some airline fares
            last twenty minutes from their search) — pay before it passes. It is
            NOT a price hold: the supplier guarantees neither the price nor
            availability for the window, so an offer can lapse inside it. Nor is
            it the lifetime of `checkout_url`, which stays openable longer.
            After this instant the platform REFUSES to take payment rather than
            charging a stale price: `POST /v1/agent_payment/submit` answers
            **410 `QUOTE_EXPIRED`** and no payment object is created. To
            recover, call `POST /v1/checkout` again on the same trip — it
            re-quotes at the current price — and pay against the new
            `expires_at`. The hosted page cannot recover on its own: past this
            instant it shows the price as expired and the customer has to be
            sent a fresh checkout. The quote can also stop being payable before
            this instant if the trip's travelers change after pricing: payment
            is then refused with **410 `QUOTE_EXPIRED`** and `reason:
            travelers_changed`."
          example: "2026-06-01T12:39:56Z"
        payment_type:
          type: string
          enum:
            - intent
            - checkout
            - agent
          description: "Which payment rail this trip is on. None of the values means
            payment has been collected: checkout only prices the trip, and you
            must still act to get it paid. `intent` — nothing has been charged
            or authorized yet; this is what a trip created through this API
            returns. Send the traveler to `checkout_url` to pay on the Jinko
            checkout page, or pay programmatically with POST
            /v1/agent_payment/submit using a type listed in
            `accepted_payment_types`. `checkout` — a payment page is already
            open for this trip; send the traveler to `checkout_url` to complete
            it. `agent` — a programmatic payment was already submitted for this
            quote through POST /v1/agent_payment/submit; check its outcome
            before submitting again. To choose how to pay, read
            `accepted_payment_types` and `agent_spt_params`, not this field."
          example: intent
        total_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `total_amount_money` instead. The trip total in
                major currency units."
              deprecated: true
        total_amount_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The trip total the checkout is priced at.
        items:
          type: array
          items:
            $ref: "#/components/schemas/TripItem"
        agent_spt_params:
          $ref: "#/components/schemas/AgentSPTParams"
      required:
        - quote_id
        - quoted_cart_id
        - accepted_payment_types
    QuoteExpiredResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - QUOTE_EXPIRED
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        expires_at:
          type: string
          description: The instant the refused quote expired (RFC 3339). For a deadline
            lapse this is the past deadline; when `reason` is
            `travelers_changed` it is the instant of the refusal.
          example: "2026-09-04T12:39:56Z"
        quote_id:
          type: string
          description: The quote that was refused — the same `quote_id` the trip and
            checkout responses carry, so a caller holding several can tell which
            one this refusal is about.
          example: "2097152"
        quoted_cart_id:
          type: number
          description: "Deprecated: use `quote_id` instead. The same quote as an integer."
          example: 2097152
          deprecated: true
        reason:
          type: string
          enum: &a22
            - travelers_changed
          description: "Present when the quote was invalidated because the trip's
            travelers changed after it was priced (`travelers_changed`). Absent
            for a plain deadline lapse. Either way the recovery is the same:
            call `POST /v1/checkout` again to re-quote, then pay against the new
            quote."
          example: travelers_changed
      required:
        - error
    MissingCustomerDetailsResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - MISSING_CUSTOMER_DETAILS
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        missing_fields:
          type: array
          items:
            type: string
          description: Field names the booking still needs, in the trip traveler
            vocabulary (e.g. `passport_number`).
          example:
            - nationality
            - passport_country
            - passport_expiry
            - passport_number
        missing_by_domain:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: The same fields grouped by product domain (e.g. `flight`).
          example:
            flight:
              - passport_number
              - passport_expiry
              - passport_country
              - nationality
      required:
        - error
    CheckoutRequest:
      type: object
      properties:
        trip_id:
          type: string
          example: trip_1048576
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - trip_id
    AgentPaymentSubmitResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: The quote this payment was taken against. This submission names no
            quote, so it pays the trip’s latest payable quote; compare this with
            the `quote_id` the traveler approved.
          example: "2097152"
        fulfillment_cart_id:
          type: integer
          description: "Deprecated: use `booking_ref` instead. An internal number for the
            booking."
          deprecated: true
        status:
          type: string
          example: processing
        payment_verified:
          type: boolean
        message:
          type: string
        booking_ref:
          type: string
          description: "The Jinko booking reference for the trip just paid — hand it to
            `POST /v1/get_booking` (`booking_ref`) to retrieve or service the
            booking. Present when the token was authorized (and when the trip
            was already past payment); absent when the payment could not be
            authorized and `checkout_url` is returned instead. When
            `payment_status` is `requires_authentication` it can be present
            before payment completes: read `payment_status`, not this field, to
            tell whether the payment went through."
          example: JNK-XEVGW5
        checkout_url:
          type: string
          description: Hosted-checkout fallback, present when the payment could not be
            authorized (for example a card decline). Not returned when
            `payment_status` is `requires_authentication`.
        recap_token:
          type: string
        payment_status:
          type: string
          description: "Status of the payment attempt behind this submission:
            `requires_authentication`, `pending`, `authorized`, `captured`,
            `declined`, `failed`, `cancelling`, `cancelled` or `expired`.
            `requires_authentication`: the card issuer asked for 3-D Secure;
            `payment_verified` is false and no `checkout_url` is returned. Send
            the traveler to `authentication_url`, with the Shared Payment
            Token's hashed value appended as that field describes, to complete
            it before `quote_expires_at`, then poll `GET /v1/trip/{trip_id}`
            until `payment_attempt.payment_status` is none of
            `requires_authentication`, `cancelling` or `pending` (`cancelling`
            is a transient cleanup state and `pending` is still in progress —
            keep polling). `authorized` / `captured`: the payment went through.
            `failed` / `declined` / `cancelled`: it did not — submit again with
            a new token before `quote_expires_at`. `expired`: it did not, and
            the quote expired with it — call `POST /v1/checkout` again to price
            a new quote, then mint and submit a new token."
          example: requires_authentication
        quote_expires_at:
          type: string
          format: date-time
          description: "Deadline for completing this payment, including 3-D Secure
            authentication (RFC 3339). After it the quote has expired: call
            `POST /v1/checkout` again for a new quote, then submit a new token."
          example: "2026-06-01T12:39:56Z"
        authentication_url:
          type: string
          format: uri
          description: 'Jinko-hosted page where the traveler completes 3-D Secure, present
            when `payment_status` is `requires_authentication` and valid until
            `quote_expires_at`. Read the Shared Payment Token you issued from
            the Stripe API (`GET
            https://api.stripe.com/v1/shared_payment/issued_tokens/{id}` with
            your own Stripe secret key, `{id}` being the token you submitted)
            and append `#hv=` and its `next_action.use_stripe_sdk.value`,
            unchanged: `authentication_url + "#hv=" +
            next_action.use_stripe_sdk.value`. The value travels in the URL
            fragment, which keeps it out of server logs. The traveler completes
            the bank challenge on that page before `quote_expires_at`. To run
            the challenge on your own page instead, load Stripe.js with your own
            publishable key and call `stripe.handleNextAction({ hashedValue })`
            with that value. Then poll `GET /v1/trip/{trip_id}` until
            `payment_attempt.payment_status` is none of
            `requires_authentication`, `cancelling` or `pending`.'
    PaymentRefusalResponse:
      allOf:
        - $ref: "#/components/schemas/ErrorResponse"
        - type: object
          properties:
            payment_error:
              type: object
              nullable: true
              properties:
                code:
                  type: string
                  enum: *a20
                message:
                  type: string
              required:
                - code
                - message
            recovery:
              type: object
              properties:
                action:
                  type: string
                  enum: *a21
                  description: "The next step. `authenticate`: when `authentication` is present,
                    open `authentication.url` before
                    `authentication.expires_at`. For a Shared Payment Token
                    (`spt`), first read the token's
                    `next_action.use_stripe_sdk.value` with your own Stripe
                    secret key and append it unchanged: open `authentication.url
                    + \"#hv=\" + <value>`, or call `stripe.handleNextAction({
                    hashedValue })` with Stripe.js on your own page. Then poll
                    `GET
                    /v1/trip/{trip_id}/payment_attempts/{payment_attempt_id}`
                    until `payment_status` is none of `requires_authentication`,
                    `cancelling` or `pending`."
                replacement_credential_required:
                  type: boolean
              required:
                - action
                - replacement_credential_required
            expires_at:
              type: string
              description: The instant the refused quote expired (RFC 3339). For a deadline
                lapse this is the past deadline; when `reason` is
                `travelers_changed` it is the instant of the refusal.
              example: "2026-09-04T12:39:56Z"
            quote_id:
              type: string
              description: The quote that was refused — the same `quote_id` the trip and
                checkout responses carry, so a caller holding several can tell
                which one this refusal is about.
              example: "2097152"
            quoted_cart_id:
              type: number
              description: "Deprecated: use `quote_id` instead. The same quote as an integer."
              example: 2097152
              deprecated: true
            reason:
              type: string
              enum: *a22
              description: "Present when the quote was invalidated because the trip's
                travelers changed after it was priced (`travelers_changed`).
                Absent for a plain deadline lapse. Either way the recovery is
                the same: call `POST /v1/checkout` again to re-quote, then pay
                against the new quote."
              example: travelers_changed
    TypedAgentPaymentSubmitRequest:
      type: object
      properties:
        trip_id:
          type: string
        quote_id:
          type: string
          pattern: ^[1-9][0-9]{0,17}$(?![\s\S])
          description: "The quote the traveler approved: the `quote_id` checkout returned.
            The payment is taken against this quote only; a quote that is no
            longer payable is refused with 410 `QUOTE_EXPIRED` and nothing is
            charged."
          example: "2097152"
        payment:
          oneOf:
            - type: object
              properties:
                type:
                  type: string
                  enum:
                    - spt
                shared_payment_token:
                  type: string
                  minLength: 1
              required:
                - type
                - shared_payment_token
              additionalProperties: false
      required:
        - trip_id
        - quote_id
        - payment
      additionalProperties: false
    AgentPaymentSubmitRequest:
      type: object
      properties:
        trip_id:
          type: string
          example: trip_1048576
        shared_payment_token:
          type: string
          example: spt_1Nq8L2eZvKYlo2C0
      required:
        - trip_id
        - shared_payment_token
    HotelSearchContext:
      type: object
      properties:
        checkin:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        checkout:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        occupancies:
          type: array
          items:
            $ref: "#/components/schemas/Occupancy"
          minItems: 1
        currency:
          type: string
        guest_nationality:
          type: string
          minLength: 2
          maxLength: 2
        trip_id:
          type: string
      required:
        - checkin
        - checkout
        - occupancies
        - currency
      description: Normalized first-request stay and occupancy frozen by the search
        session and repeated on every page. trip_id only associates the search
        with a trip for display.
    DestinationResolution:
      type: object
      properties:
        shape:
          type: string
          enum:
            - city
            - coordinates
            - query
            - hotel_name
            - hotel_ids
          description: "Which destination selector the request used. It says which of the
            other fields are present: the city fields on `city`,
            `hotel_id`/`hotel_name`/`hotel_city` on `hotel_name`, `hotel_ids` on
            `hotel_ids`."
          example: city
        match:
          type: string
          enum:
            - exact
            - fuzzy
            - provider_matched
            - fallback_string
          description: "`exact` — the destination was found verbatim: a city catalog
            group, a place located under the name asked for (`resolved_place`),
            coordinates, hotel ids, or a hotel name scoring 1.0. `fuzzy` — a
            close-but-different label was auto-picked: on the city shape, a
            single candidate scoring ≥ 0.85 with no runner-up ≥ 0.6, or a place
            located under another name (`resolved_place`); on hotel_name, a
            lookup scoring < 1.0 — the response also carries a warning naming
            the substitution. `provider_matched` — a `query` selector was
            forwarded as-is and the supplier chose the place. `fallback_string`
            — `city_name` could not be resolved at all, so the raw string was
            forwarded to the supplier unchanged; `status` says why."
          example: exact
        status:
          type: string
          enum:
            - resolved
            - unknown_city
            - implausible_spread
            - unsupported_shape
            - resolver_unavailable
            - not_attempted
          description: City shape ONLY. Absent for coordinates, query, hotel_name and
            hotel_ids.
          example: resolved
        requested_city:
          type: string
          example: Sain Malo
        requested_country:
          type: string
          example: FR
        resolved_city:
          type: string
          example: Saint Malo
        resolved_country:
          type: string
          example: FR
        latitude:
          type: number
          example: 48.649
        longitude:
          type: number
          example: -2.0257
        radius_km:
          type: number
          description: "The radius actually searched, with `latitude`/`longitude` as its
            centre; `radius_source` says where it came from. City and query
            shapes: present when the destination resolved to a centre (a catalog
            city group or a located place). Coordinates shape: absent when the
            supplier default was used and is unknown to the platform."
        radius_source:
          type: string
          enum:
            - caller
            - city
            - default
            - place
          description: Where `radius_km` came from. `caller` — the request’s own
            `radius_km`. `city` — the resolved city’s extent (its catalog
            spread, or the located city’s size when `resolution_source` is
            `geocoder`), floored at the platform minimum. `default` — the
            platform default, for coordinates sent without a radius. `place` —
            the size of the located place for its `place_type` (a district,
            landmark, station, address, airport, island or region). A `city` or
            `default` radius may be widened when the first search finds too
            little; `radius_km` is then the radius finally searched. Absent on
            the hotel_name and hotel_ids shapes.
          example: city
        catalog_hotel_count:
          type: integer
          description: How many properties the matched city catalog group holds. Absent
            when the search centre did not come from a catalog group
            (`resolution_source` `geocoder`).
          example: 41
        place_type:
          type: string
          enum:
            - city
            - district
            - poi
            - station
            - address
            - airport
            - island
            - region
          description: "city and query shapes, when the platform located the destination
            itself: the kind of place searched. `poi` is a landmark or venue.
            More values may be added. Absent when the destination was not
            located this way."
          example: island
        resolution_source:
          type: string
          enum:
            - catalog
            - geocoder
          description: "With `place_type`: where the search centre came from. `catalog` —
            the platform’s city catalog group, used only when it agrees with the
            located place (`resolved_city` and `catalog_hotel_count` are then
            present). `geocoder` — the located place itself."
          example: geocoder
        resolved_place:
          type: string
          description: "With `place_type`: the name of the place searched, the one to
            quote back to the user."
          example: Fuerteventura, Las Palmas, Spain
        search_bounds:
          type: object
          properties:
            south:
              type: number
            west:
              type: number
            north:
              type: number
            east:
              type: number
          required:
            - south
            - west
            - north
            - east
          description: "Island and region searches only: the box, in degrees, that every
            returned hotel lies inside, so a search around an island never
            returns hotels from the next one."
          example:
            south: 28.0439
            west: -14.51
            north: 28.757
            east: -13.8224
        alternatives:
          type: array
          items:
            type: object
            properties:
              resolved_place:
                type: string
              place_type:
                type: string
                enum:
                  - city
                  - district
                  - poi
                  - station
                  - address
                  - airport
                  - island
                  - region
              resolved_country:
                type: string
              latitude:
                type: number
              longitude:
                type: number
              radius_km:
                type: number
                minimum: 0
                exclusiveMinimum: true
                maximum: 50
            required:
              - resolved_place
              - place_type
              - latitude
              - longitude
              - radius_km
          maxItems: 3
          description: "With `place_type`: up to three other places the destination may
            name — the same name in another country or state, the island or
            region around the town searched when an island or region was asked
            for, or another place the text names. To search one of them instead,
            send its `latitude`, `longitude` and `radius_km` (at most 50, the
            limit the request accepts). Absent when the destination names one
            place."
          example:
            - resolved_place: Lexington, MA, USA
              place_type: city
              resolved_country: US
              latitude: 42.4473497
              longitude: -71.2271531
              radius_km: 6.1
        score:
          type: number
          minimum: 0
          maximum: 1
          description: Only present when `match` is `fuzzy` (the city shape’s auto-pick
            similarity) or on the hotel_name shape (the name lookup’s own
            score).
          example: 0.9
        query:
          type: string
        hotel_id:
          type: string
          example: lp1d2c3
        hotel_name:
          type: string
        hotel_city:
          type: string
        nearby_alternatives_included:
          type: boolean
          description: "hotel_name shape only: true when nearby hotels were also priced."
        hotel_ids:
          type: array
          items:
            type: string
          description: "hotel_ids shape only: the ids that were rate-shopped."
        hotel_ids_without_rates:
          type: array
          items:
            type: string
          description: "hotel_name shape: present when the matched hotel priced nothing.
            hotel_ids shape: the requested ids that priced nothing."
      description: "How the request’s destination resolved into these hotels. Present
        on every successful search. Rendering rule for an agent or tool: say
        something ONLY when there is something to say — `match` is `fuzzy` or
        `fallback_string`, `resolved_city` differs from `requested_city`, or the
        platform located a place that is not a city (`place_type` other than
        `city`), or `alternatives` is present. `exact` and `provider_matched`
        otherwise need no header line of their own. When `resolved_place` is
        present, name it as the place searched, with `place_type` when it is not
        a city, instead of `resolved_city`. When `alternatives` is present, name
        them too and let the user pick before booking."
    EmptyReason:
      type: string
      enum:
        - no_availability_for_dates
        - destination_not_found
        - catalog_exhausted
        - all_dropped_by_budget
        - no_catalog_match
        - all_dropped_by_star_filter
        - all_dropped_by_rating_filter
      description: Why `hotels` is empty. Absent whenever `hotels` is non-empty.
      example: no_availability_for_dates
    HotelSearchResponse:
      type: object
      properties:
        hotels:
          type: array
          items:
            $ref: "#/components/schemas/Hotel"
        nearby_alternatives:
          type: array
          items:
            $ref: "#/components/schemas/Hotel"
          description: Other hotels near the one a `hotel_name` search matched, priced for
            the same dates and occupancy, so they can be compared without a
            second search. Same shape as `hotels`, and not counted in `total`.
            Present only on a `hotel_name` search that found usable neighbours.
        total:
          type: number
          example: 87
        search_handle:
          type: string
          description: "Deprecated: use `next_handle` instead. The identifier of the
            search session on its own, which no endpoint accepts. `next_handle`
            carries the session and the next page, `has_more` says whether there
            is one and `expires_at` when the session ends."
          deprecated: true
          example: hs_example
        next_handle:
          type: string
          nullable: true
          description: Opaque handle for the next deterministic page. Send it by itself to
            hotel_search. Null means the fixed search scope is exhausted.
          example: hp_example_2
        has_more:
          type: boolean
          description: Whether this fixed search session has another page.
        expires_at:
          type: string
          format: date-time
          description: RFC 3339 expiry for the search session and its page handles.
          example: "2027-01-15T10:30:00Z"
        search_context:
          $ref: "#/components/schemas/HotelSearchContext"
        warnings:
          type: array
          items:
            type: string
          description: Non-fatal advisories, e.g. budget-filter outcomes or ignored filters.
        destination_resolution:
          $ref: "#/components/schemas/DestinationResolution"
        empty_reason:
          $ref: "#/components/schemas/EmptyReason"
    HotelNameCandidate:
      type: object
      properties:
        hotel_id:
          type: string
          example: lp1a2b3c
        name:
          type: string
          example: Hotel Le Marais
        city:
          type: string
          example: Paris
        score:
          type: number
          minimum: 0
          maximum: 1
          example: 0.82
      required:
        - hotel_id
        - name
        - score
    LowConfidenceSuggestedRetry:
      type: object
      properties:
        destination:
          type: object
          additionalProperties:
            nullable: true
          description: The exact fields to retry the search with — merge into the failed
            request unchanged for an exact match.
          example:
            city_name: Saint Malo
            country_code: FR
        rationale:
          type: string
          example: the closest catalog city to the requested name; retry with it, or ask
            the user when the candidates differ
      required:
        - destination
      description: The one-shot fix, when the top candidate is confident enough to name one.
    HotelNameLowConfidenceResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - HOTEL_NAME_LOW_CONFIDENCE
            message:
              type: string
            doc_url:
              type: string
            top_candidates:
              type: array
              items:
                $ref: "#/components/schemas/HotelNameCandidate"
              description: Closest matches, ordered by score descending, at most 5.
            suggested_retry:
              $ref: "#/components/schemas/LowConfidenceSuggestedRetry"
          required:
            - code
            - message
            - top_candidates
      required:
        - error
    DestinationCityCandidate:
      type: object
      properties:
        city:
          type: string
          example: Saint Malo
        country_code:
          type: string
          example: FR
        hotel_count:
          type: integer
          example: 326
        score:
          type: number
          minimum: 0
          maximum: 1
          example: 0.75
      required:
        - city
        - country_code
        - hotel_count
        - score
    DestinationLowConfidenceResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - DESTINATION_LOW_CONFIDENCE
            message:
              type: string
            doc_url:
              type: string
            top_candidates:
              type: array
              items:
                $ref: "#/components/schemas/DestinationCityCandidate"
              description: Closest catalog cities, ordered by score descending, at most 5.
            suggested_retry:
              $ref: "#/components/schemas/LowConfidenceSuggestedRetry"
          required:
            - code
            - message
            - top_candidates
      required:
        - error
    HotelSearchContinuationRequest:
      type: object
      properties:
        next_handle:
          type: string
          minLength: 1
          description: Opaque continuation handle returned by a prior hotel_search. Send
            this field by itself; the search session keeps destination, dates,
            occupancy, currency and filters.
          example: hp_example_2
      required:
        - next_handle
      additionalProperties: false
    HotelSearchRequest:
      anyOf:
        - $ref: "#/components/schemas/HotelSearchContinuationRequest"
        - type: object
          properties:
            next_handle:
              not: {}
            query:
              type: string
              example: Paris
            city_name:
              type: string
            country_code:
              type: string
              minLength: 2
              maxLength: 2
            latitude:
              type: number
            longitude:
              type: number
            radius_km:
              type: number
              minimum: 0
              exclusiveMinimum: true
              maximum: 50
            hotel_ids:
              type: array
              items:
                type: string
            hotel_name:
              type: string
              minLength: 1
              description: Search one specific hotel by its name. The name is matched against
                the hotel catalog; the closest match is priced when it scores at
                least 0.7, and the response then has
                `destination_resolution.shape` `hotel_name` plus
                `nearby_alternatives` within 3 km. Add `city_name` and
                `country_code` to narrow the match. When no candidate scores
                0.7, the call returns 422 `HOTEL_NAME_LOW_CONFIDENCE` with
                `top_candidates` and a `suggested_retry`. With `hotel_name`,
                `query`, `city_name` and coordinates do not set the search area.
                Property filters (min_rating, min_star_rating, max_star_rating,
                star_rating, min_reviews, hotel_type_ids, chain_ids,
                facility_ids) are not accepted with hotel_name or hotel_ids and
                are rejected with 400. `hotel_ids`, when also sent, takes
                precedence. Name lookup covers part of the hotel inventory only.
              example: Park Plaza Beijing Wangfujing
            checkin:
              type: string
              pattern: ^\d{4}-\d{2}-\d{2}$
              description: Arrival date, `YYYY-MM-DD`. Today (UTC) or later.
            checkout:
              type: string
              pattern: ^\d{4}-\d{2}-\d{2}$
              description: "Departure date, `YYYY-MM-DD`. After `checkin`: a stay has at least
                one night."
            occupancies:
              type: array
              items:
                $ref: "#/components/schemas/Occupancy"
              description: Each array element requests one room. One occupancy returns a
                one-room offer and keeps the deprecated `rooms[].rates[]`
                compatibility projection; multiple occupancies return multi-room
                `offers[]`. Add the chosen offer’s trip_item_token to a trip
                once.
            adults:
              type: integer
              minimum: 1
              description: "Deprecated: use `occupancies` instead, one element per room with
                its own `adults`. Shorthand for the adults of the whole party:
                without `rooms` one room is priced for all of them, with `rooms`
                they are spread evenly over that many rooms. Ignored when
                `occupancies` is sent."
              deprecated: true
            children:
              type: array
              items:
                type: integer
                minimum: 0
                maximum: 17
              description: "Deprecated: use `occupancies[].children_ages` instead, which
                places each child in a room. Shorthand for the age of each child
                of the whole party, spread over the rooms of `rooms`. Ignored
                when `occupancies` is sent."
              deprecated: true
            rooms:
              type: integer
              minimum: 1
              description: "Deprecated: use `occupancies` instead, one element per room.
                Shorthand for how many rooms the `adults` and `children` of the
                party are spread over, evenly. Ignored when `occupancies` is
                sent."
              deprecated: true
            currency:
              type: string
            guest_nationality:
              type: string
              minLength: 2
              maxLength: 2
              description: The lead guest’s nationality, ISO 3166-1 alpha-2 (`FR`). Sent to
                the hotel supplier, which can offer different rates and prices
                by nationality, and kept on the offers this search returns. When
                omitted, `US` is used. The value applied is echoed in
                `search_context.guest_nationality`.
              example: FR
            min_rating:
              type: number
              description: Minimum guest score (0-10) for destination searches. When omitted,
                or 0, no floor applies, and hotels without a guest score are
                returned too. Not accepted together with hotel_name or
                hotel_ids.
            min_star_rating:
              type: integer
              minimum: 1
              maximum: 5
            star_rating:
              type: integer
              minimum: 1
              maximum: 5
              description: "Deprecated: use `min_star_rating` and `max_star_rating` instead;
                send the same value as both for an exact match. Still applied:
                it fills whichever of the two bounds the request leaves unset."
              deprecated: true
            max_star_rating:
              type: integer
              minimum: 1
              maximum: 5
            min_reviews:
              type: integer
              description: Minimum number of guest reviews.
            max_results:
              type: integer
              description: Requested page size (default 50); next_handle returns the next page
                of the same search. A hotel_name or hotel_ids search returns
                every named hotel that has rates.
            offset:
              type: integer
              minimum: 0
              description: "Deprecated: use `next_handle` instead. Skips this many hotels at
                the hotel source before the first page, default 0. A search that
                answers with `next_handle` refuses a non-zero offset: page by
                sending that handle alone."
              deprecated: true
            max_budget_per_night:
              type: number
              minimum: 0
              exclusiveMinimum: true
              description: Keep only hotels whose cheapest per-night price (per room, in the
                request currency) is within this budget; qualifying hotels keep
                all their rates.
              example: 150
            hotel_type_ids:
              type: array
              items:
                type: string
              description: Filter by property type id. Each entry is a numeric property type
                id, as a string; property type names are refused.
            chain_ids:
              type: array
              items:
                type: string
            facility_ids:
              type: array
              items:
                type: string
              description: Filter by facility. Each entry is a Jinko facility dictionary id
                (numeric, as a string), listed in the docs under Hotel facility
                dictionary. Facility names are refused on this endpoint.
            intent:
              $ref: "#/components/schemas/IntentInput"
          required:
            - checkin
            - checkout
      example:
        city_name: Paris
        country_code: fr
        checkin: "2027-03-10"
        checkout: "2027-03-13"
        occupancies:
          - adults: 2
        currency: USD
    HotelPolicy:
      type: object
      properties:
        name:
          type: string
          example: Pets
        description:
          type: string
          example: Pets are not allowed.
        policy_type:
          type: string
          example: pets
        child_allowed:
          type: boolean
          description: Whether this policy says the property accepts children. Absent when
            it does not say.
          example: true
        pets_allowed:
          type: boolean
          description: Whether this policy says the property accepts pets. Absent when it
            does not say.
          example: false
    HotelDetailsRoom:
      type: object
      properties:
        id:
          type: string
          example: rm_1
        name:
          type: string
          example: Superior Double
        description:
          type: string
        amenities:
          type: array
          items:
            type: string
          example:
            - Air conditioning
            - Safe
        amenity_items:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Stable numeric id.
              label:
                type: string
                description: English label.
            required:
              - id
              - label
          description: Room amenities with a stable amenity id. Room amenity ids are a
            separate list from the facility dictionary.
          example:
            - id: 312
              label: Shower
            - id: 339
              label: TV
        bed_types:
          type: array
          items:
            type: string
          example:
            - 1 double bed
        room_capacity:
          type: integer
          description: How many the room sleeps, from the property’s own room metadata.
            Same field as on hotel_search and on a hotel trip item.
          example: 2
        max_occupancy:
          type: integer
          description: "Deprecated: use `room_capacity` (same value)."
          deprecated: true
          example: 2
        max_adults:
          type: integer
          description: Maximum number of adults the room accepts.
          example: 2
        max_children:
          type: integer
          description: Maximum number of children the room accepts; 0 means the room does
            not take children.
          example: 1
        size_sqm:
          type: number
          example: 18.5
        views:
          type: array
          items:
            type: string
          example:
            - Courtyard
        images:
          type: array
          items:
            type: string
    HotelDetailsResponse:
      type: object
      properties:
        hotel:
          type: object
          properties:
            id:
              type: string
              description: Opaque hotel identifier, the value hotel_search returns as
                `hotel_id`. Pass it back exactly as received; do not parse or
                build it.
              example: lp1d2c3
            hotel_ref:
              type: string
              description: "Deprecated: use `hotel_id` (search) or `id` (details, reviews).
                The hotel's identifier behind a source prefix, as earlier
                contract versions returned it; hotel_details and hotel_reviews
                still accept it. Pass it back exactly as received; do not parse
                or build it."
              example: h1:lp1d2c3
              deprecated: true
            name:
              type: string
              example: Hôtel Le Marais
            description:
              type: string
              example: A boutique 4-star hotel in the heart of the Marais district.
            star_rating:
              type: number
              example: 4
            rating:
              type: number
              description: Guest score out of 10.
              example: 8.6
            review_count:
              type: integer
              description: Number of guest reviews behind `rating`.
              example: 1243
            child_allowed:
              type: boolean
              description: Whether the property accepts children. Absent when the property
                does not say; `false` is a stated no.
              example: true
            pets_allowed:
              type: boolean
              description: Whether the property accepts pets. Absent when the property does
                not say; `false` is a stated no.
              example: false
            address:
              type: string
              example: 12 Rue de Rivoli
            city:
              type: string
              example: Paris
            country_code:
              type: string
              example: FR
            coordinates:
              type: object
              properties:
                latitude:
                  type: number
                longitude:
                  type: number
              example:
                latitude: 48.8566
                longitude: 2.3522
            images:
              type: array
              items:
                type: string
              example:
                - https://images.gojinko.com/hotels/htl_8f21a9c0/1.jpg
            facilities:
              type: array
              items:
                type: string
              example:
                - Free WiFi
                - Air conditioning
                - 24-hour front desk
            facility_items:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: integer
                    description: Stable numeric id.
                  label:
                    type: string
                    description: English label.
                required:
                  - id
                  - label
              description: "Facilities as dictionary entries: `id` is the Jinko facility
                dictionary id (the value `facility_ids` accepts on
                hotel_search), `label` the English label. Facilities without a
                dictionary id appear in `facilities` only."
              example:
                - id: 107
                  label: Free WiFi
                - id: 2
                  label: Air conditioning
            policies:
              type: array
              items:
                $ref: "#/components/schemas/HotelPolicy"
            check_in_time:
              type: string
              example: "15:00"
            check_out_time:
              type: string
              example: "11:00"
        rooms:
          type: array
          items:
            $ref: "#/components/schemas/HotelDetailsRoom"
          description: Room-level metadata for this property. These are DESCRIPTIVE only
            and carry no price — `room_id` correlates them to the priced rooms
            in a hotel_search response.
    HotelReviewsResponse:
      type: object
      properties:
        hotel:
          type: object
          properties:
            id:
              type: string
              description: Opaque hotel identifier, the value hotel_search returns as
                `hotel_id` and hotel_details as `id`. Pass it back exactly as
                received; do not parse or build it.
              example: lp39fe9
            hotel_ref:
              type: string
              description: "Deprecated: use `hotel_id` (search) or `id` (details, reviews).
                The hotel's identifier behind a source prefix, as earlier
                contract versions returned it; hotel_details and hotel_reviews
                still accept it. Pass it back exactly as received; do not parse
                or build it."
              example: h1:lp1d2c3
              deprecated: true
            name:
              type: string
              description: Hotel name.
              example: Park Plaza Beijing Wangfujing
            rating:
              type: number
              description: Guest score out of 10.
              example: 8.6
            review_count:
              type: integer
              description: Number of guest reviews behind `rating`.
              example: 1243
          required:
            - id
          description: The hotel the reviews are about.
        summary:
          type: object
          nullable: true
          properties:
            pros:
              type: array
              items:
                type: string
              description: What guests praise, as short phrases.
              example:
                - Central location
                - Helpful staff
            cons:
              type: array
              items:
                type: string
              description: What guests criticise, as short phrases.
              example:
                - Small rooms
            categories:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                    description: Category name.
                    example: Cleanliness
                  rating:
                    type: number
                    description: Category score out of 10.
                    example: 8.9
                  description:
                    type: string
                    description: What guests say about this category.
                    example: Guests praise the housekeeping.
              description: Score per category, such as cleanliness, location or staff.
              example:
                - name: Cleanliness
                  rating: 8.9
                  description: Guests praise the housekeeping.
            updated_at:
              type: string
              description: When the summary was last updated (RFC 3339). Absent when unknown.
              example: "2026-09-30T00:00:00Z"
          required:
            - pros
            - cons
            - categories
          description: Summary of what guests say. Null when the hotel has no review
            summary.
        reviews:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                description: Review id.
                example: "12345"
              headline:
                type: string
                description: Review title.
                example: Great stay
              score:
                type: number
                description: This reviewer's score out of 10.
                example: 9
              pros:
                type: string
                description: What this reviewer liked, as they wrote it.
                example: Location, breakfast
              cons:
                type: string
                description: What this reviewer disliked, as they wrote it.
                example: Street noise at night
              date:
                type: string
                description: Review date, `YYYY-MM-DD`. Absent when unknown.
                example: "2026-09-12"
              language:
                type: string
                description: Language code of the review.
                example: en
              reviewer_name:
                type: string
                description: The reviewer's display name.
                example: Ana
          description: One page of individual reviews, newest first. Empty when the hotel
            has no reviews or the page starts past the last one.
          example:
            - id: "12345"
              headline: Great stay
              score: 9
              pros: Location, breakfast
              cons: Street noise at night
              date: "2026-09-12"
              language: en
              reviewer_name: Ana
        page:
          type: object
          properties:
            limit:
              type: integer
              description: Reviews requested per page.
              example: 10
            offset:
              type: integer
              description: Reviews skipped before this page.
              example: 0
            total_count:
              type: integer
              nullable: true
              description: Total reviews available for this hotel, when known.
              example: 1243
          required:
            - limit
            - offset
            - total_count
          description: Where this page sits among the hotel's reviews.
      required:
        - hotel
        - summary
        - reviews
        - page
    BestPriceGuaranteeOffer:
      type: object
      properties:
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. Same value."
          example: htl_neg_ogydqmrsgaydamjqgezdgnbvgy
          deprecated: true
        trip_item_token:
          type: string
          description: "The new offer. Pass it as `add_item.trip_item_token` to `POST
            /v1/trip`, then check out as for any hotel offer. A trip that holds
            it can hold nothing else: start a new trip, or send `remove_item`
            for the offer it replaces together with `add_item` in one call.
            Adding it beside another item is refused with 409."
          example: htl_neg_ogydqmrsgaydamjqgezdgnbvgy
        price_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "What the new offer costs, payable at booking: the price matched to
                the reference. The price at checkout can move with the
                supplier."
        original:
          type: object
          properties:
            kind:
              type: string
              description: "How the Jinko product was named in the request. `offer`: a hotel
                search offer, in `trip_item_token`. Other kinds may be added;
                read the fields that kind names."
              example: offer
            trip_item_token:
              type: string
              description: The offer that was submitted. Present when `kind` is `offer`.
              example: htl_8f3c1d5e9a7b2c40
            offer_id:
              type: string
              description: "Deprecated: use `trip_item_token` instead. Same value."
              example: htl_8f3c1d5e9a7b2c40
              deprecated: true
            total_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: "The standard price of the same rate at the time of the review. It
                    can be lower than the price the earlier search showed for
                    the submitted offer: a search for one hotel can price a rate
                    lower than an area search did."
          required:
            - kind
            - total_money
          description: The offer the new one replaces, and its standard price.
        reference:
          type: object
          properties:
            total_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The reference price as submitted.
            verified:
              type: boolean
              description: "`true` when Jinko read the reference page and it showed the same
                stay at or under the submitted total."
              example: true
          required:
            - total_money
            - verified
          description: The reference the offer was reviewed against.
        saving_money:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "`original.total_money` minus `price_money`: the saving against the
                current standard price. Zero when that price was already at or
                below the reference."
        expires_at:
          type: string
          description: Until when the new offer can be added to a trip (RFC 3339, UTC). At
            most 30 minutes after the review.
          example: "2026-10-12T10:30:00Z"
      required:
        - offer_id
        - trip_item_token
        - price_money
        - original
        - reference
        - saving_money
        - expires_at
    BestPriceGuaranteeDeclineReason:
      type: string
      description: 'Why there is no offer. The reasons known today are listed here;
        the set grows, so treat a reason that is not listed as "no offer".
        `feature_disabled`: Best Price Guarantee is not enabled for this key.
        `product_not_found`: the offer is not known, or older than 75 minutes —
        search again. `product_not_supported`: not a single-room hotel offer
        from a search. `rate_unavailable`: the same room, board and cancellation
        terms could not be found again — search again and resubmit.
        `reference_source_not_allowed`, `reference_invalid`,
        `currency_mismatch`: the reference cannot be used as submitted.
        `price_cannot_be_matched`: this price cannot be offered for this rate.
        `reference_not_lower`: the current price of this rate is already at or
        below the reference. After either of these two, search the hotel alone
        (`hotel_ids`) to get its current price: it can be lower than the price
        the earlier search showed. `objective_not_supported`: the requested
        objective is not available. `temporarily_unavailable`, `timeout`: the
        review did not complete — submitting again may succeed. Reasons from the
        check of the reference page, each with a specific `decline.detail`:
        `hotel_mismatch`: the page is for another hotel; `stay_mismatch`: the
        link or the page is for other dates or another number of guests, so it
        cannot be compared; `conditions_mismatch`: the page sells the stay only
        with another room, board or cancellation terms; `reference_mismatch`:
        the page shows a higher total for the stay than the reference
        submitted.'
      example: price_cannot_be_matched
    BestPriceGuaranteeResponse:
      type: object
      properties:
        id:
          type: string
          description: Identifies the request; read its result with `GET
            /v1/best_price_guarantee/{id}`. Absent when the submission was
            declined before being recorded (`feature_disabled`, an unknown
            product).
          example: ngo_mfrggzdfmztwq2lknnwg23tpob
        status:
          type: string
          description: "`pending`: the review is still running — read the request again;
            this is not a decline. It can take up to a few minutes when the
            reference page is checked. `offered`: `offer` holds the new offer.
            `declined`: no offer, see `decline.reason`. `expired`: an offer was
            made and not used before `expires_at`. Treat any other value as
            `pending`."
          example: offered
        poll_after_seconds:
          type: integer
          description: "Present while `status` is `pending`: a suggested pause before
            reading again."
          example: 2
        offer:
          $ref: "#/components/schemas/BestPriceGuaranteeOffer"
        decline:
          type: object
          properties:
            reason:
              $ref: "#/components/schemas/BestPriceGuaranteeDeclineReason"
            detail:
              type: string
              description: "What the check of the reference page found, when the decline comes
                from it. Written for the traveller: pass it on as it is."
              example: the page shows a stay from 2026-11-20 to 2026-11-22; the Jinko offer is
                from 2026-11-17 to 2026-11-19
          required:
            - reason
          description: Present when `status` is `declined`.
      required:
        - status
      example:
        id: ngo_mfrggzdfmztwq2lknnwg23tpob
        status: offered
        offer:
          trip_item_token: htl_neg_ogydqmrsgaydamjqgezdgnbvgy
          offer_id: htl_neg_ogydqmrsgaydamjqgezdgnbvgy
          price_money:
            value: 41250
            currency: USD
            decimal_places: 2
            display: USD 412.50
          original:
            kind: offer
            trip_item_token: htl_8f3c1d5e9a7b2c40
            offer_id: htl_8f3c1d5e9a7b2c40
            total_money:
              value: 43780
              currency: USD
              decimal_places: 2
              display: USD 437.80
          reference:
            total_money:
              value: 41250
              currency: USD
              decimal_places: 2
              display: USD 412.50
            verified: true
          saving_money:
            value: 2530
            currency: USD
            decimal_places: 2
            display: USD 25.30
          expires_at: "2026-10-12T10:30:00Z"
    BestPriceGuaranteeReference:
      type: object
      properties:
        url:
          type: string
          minLength: 1
          description: The https link to the page where the traveller saw the lower price.
            It must be on a site accepted as a reference; another site is
            answered `declined` with reason `reference_source_not_allowed`.
          example: https://www.booking.com/hotel/fr/example.html?checkin=2026-11-10
        screenshot_url:
          type: string
          minLength: 1
          description: "An https address a screenshot of that page can be downloaded from.
            Required on most accounts: a submission without it is then answered
            `declined` with reason `reference_invalid`."
          example: https://files.example.com/screenshots/8f3.png
        total:
          type: string
          minLength: 1
          description: "The total payable AT BOOKING on that page, as a plain decimal
            string: no currency symbol, no thousands separator, at most the
            decimal places of `currency`. Taxes payable at the property are not
            part of it."
          example: "412.50"
        currency:
          type: string
          minLength: 3
          maxLength: 3
          description: The ISO 4217 currency of `total`. It must be the currency of the
            offer being compared (`total_amount_money.currency` of the offer in
            `hotel_search`). A price in another currency is answered `declined`
            with reason `currency_mismatch`; nothing is converted.
          example: USD
      required:
        - url
        - total
        - currency
    BestPriceGuaranteeRequest:
      type: object
      properties:
        product:
          type: string
          enum:
            - hotel
          description: The kind of product the request is about. Only `hotel` exists today.
          example: hotel
        objective:
          type: string
          enum:
            - price_parity
          description: What is asked for. `price_parity` (the default, and the only value
            today) asks for the reference price, nothing lower.
          example: price_parity
        trip_item_token:
          type: string
          minLength: 1
          description: "The hotel offer the traveller compared:
            `hotels[].offers[].trip_item_token` from `POST /v1/hotel_search`. It
            names the hotel, the dates, the party and the rate. An offer is kept
            for 75 minutes after the search that returned it."
          example: htl_8f3c1d5e9a7b2c40
        reference:
          $ref: "#/components/schemas/BestPriceGuaranteeReference"
        wait_seconds:
          type: integer
          minimum: 0
          maximum: 20
          description: "How long this call waits for the result before answering, 0–20
            seconds (default 0: answer at once). It only decides when the call
            returns; the review continues either way, and a call that waited
            without a result answers `pending`."
          example: 15
      required:
        - product
        - trip_item_token
        - reference
    CarImage:
      type: object
      properties:
        url:
          type: string
          example: https://images.example.com/cars/6f2a.jpg
      description: "One supplier-published photo of the vehicle class. Only the URL is
        carried: the provider labels a size rather than publishing pixel
        dimensions."
    CarVehicle:
      type: object
      properties:
        acriss_code:
          type: string
          example: CDMR
        name:
          type: string
          example: Honda Accord or similar
        category:
          type: string
          example: compact
        type:
          type: string
          example: sedan
        transmission:
          type: string
          example: manual
        fuel_type:
          type: string
        seats:
          type: string
          description: A string — suppliers publish ranges like "5-7".
          example: "5"
        doors:
          type: string
          description: A string, like seats.
        big_suitcases:
          type: integer
          example: 2
        small_suitcases:
          type: integer
          example: 1
        air_conditioned:
          type: boolean
        built_in_gps:
          type: boolean
        model_guaranteed:
          type: boolean
          description: 'False is the ordinary "or similar" rental promise: the supplier
            guarantees the class, not this exact model. Do not present the model
            as confirmed unless this is true.'
        supplier_code:
          type: string
          description: The supplier's own code for this vehicle class, not for the rental
            company — cars from one company carry many different values here.
            Opaque; do not parse or match companies on it.
          example: D
        images:
          type: array
          items:
            $ref: "#/components/schemas/CarImage"
    CarAmount:
      type: object
      properties:
        value:
          type: integer
          description: "Integer amount in MINOR units, always paired with decimal_places —
            divide by 10 ** decimal_places to display. Example: value 15977 with
            decimal_places 2 is 159.77 USD. Rendering this field directly shows
            prices 100x too high for 2-decimal currencies."
          example: 41250
        currency:
          type: string
          description: ISO 4217 currency code.
          example: EUR
        decimal_places:
          type: integer
          description: "Scale of the integer value/amount: display = integer / 10 **
            decimal_places. Always sent alongside minor-unit amounts. Usually
            the ISO 4217 digits of the currency (2 for USD/EUR/GBP, 0 for
            JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices can carry
            a different scale — ALWAYS use the decimal_places sent with the
            amount, never a hardcoded 2. Only if the field is genuinely absent
            on a value-shaped object, fall back to the ISO digits for the
            currency."
          example: 2
        display:
          type: string
          description: 'The same figure as a string ready to show: the ISO 4217 code, a
            space, then the amount, e.g. "USD 159.77". With decimal_places it is
            written at exactly that scale (value 1561500, JPY, decimal_places 2
            is "JPY 15615.00"); without, at the ISO digits of the currency. Show
            this; compute with the number. Absent when the figure is not money
            (a cancellation step expressed as a percent or a number of nights)
            or could not be read unambiguously.'
          example: EUR 412.50
    CarCoverage:
      type: object
      properties:
        name:
          type: string
          example: Collision Damage Waiver
        excess:
          $ref: "#/components/schemas/CarAmount"
        included_in_vehicle_price:
          type: boolean
        mandatory:
          type: boolean
        paid_at:
          type: string
          example: now
        price:
          $ref: "#/components/schemas/CarAmount"
      description: One insurance line on a package. `excess` is the driver’s maximum
        liability under it — absent when the supplier stated none, which is not
        zero excess. `price` is the line’s own charge when it is not already
        inside the vehicle price.
    CarFee:
      type: object
      properties:
        name:
          type: string
          example: One-way fee
        included_in_vehicle_price:
          type: boolean
        mandatory:
          type: boolean
        paid_at:
          type: string
          example: local
        price:
          $ref: "#/components/schemas/CarAmount"
      description: One fee attached to the rental, with when it is paid (`paid_at`)
        and whether it is already inside the vehicle price.
    CarPackage:
      type: object
      properties:
        name:
          type: string
          example: Fully Inclusive
        code:
          type: string
          description: The provider's own code for this rate package. Opaque.
          example: FI
        supplier_name:
          type: string
          description: The rental company the driver actually collects the car from —
            Avis, Hertz, Europcar, Sixt. It is that company, not Jinko or any
            intermediary, whose desk, deposit rules and fuel policy apply, so it
            is the supplier identity to show a customer. Read off the pick-up
            branch, so a one-way rental names the collecting company, never the
            returning one.
          example: Avis
        supplier_code:
          type: string
          description: The pick-up branch's own code, scoped to a station rather than to a
            company. Opaque, and NOT comparable with vehicle.supplier_code —
            match companies on supplier_name.
          example: DEMO_BCN
        fuel_policy:
          type: string
          example: full_to_full
        mileage_unlimited:
          type: boolean
        mileage_allowance:
          type: string
        inclusions:
          type: array
          items:
            nullable: true
        coverages:
          type: array
          items:
            $ref: "#/components/schemas/CarCoverage"
        fees:
          type: array
          items:
            $ref: "#/components/schemas/CarFee"
    CarBranch:
      type: object
      properties:
        name:
          type: string
          example: Lyon Saint-Exupery Airport
        address:
          type: string
        city:
          type: string
          example: Lyon
        country:
          type: string
          example: FR
        phone:
          type: string
        date_time:
          type: string
          description: The pick-up or drop-off time at this branch, branch-local.
          example: "2026-09-12T10:00:00"
        time_zone:
          type: string
          example: Europe/Paris
        latitude:
          type: number
        longitude:
          type: number
        opening_hours:
          type: string
          description: The branch's published hours, as supplied. Free text, not a
            parseable schedule.
        out_of_hours:
          type: boolean
          description: This pick-up or drop-off falls outside the published hours, which
            usually carries a surcharge. Only asserted when that day's hours
            were published, so false means "within hours, or not stated" and
            never "checked and fine".
        requires_flight_number:
          type: string
          description: 'The branch policy: "never", "always" or "out_of_hours_pickup".
            Jinko carries no flight number today, so "always" means this branch
            cannot be booked — prefer an offer from another branch.'
          example: never
        terminals:
          type: array
          items:
            type: string
          description: The airport terminals this branch serves, when it is at one.
        is_meet_and_greet:
          type: boolean
          description: The supplier meets the driver instead of staffing a desk, so there
            is nowhere to walk up to. Tell the customer to expect a meeting
            point.
    CarOfferPrice:
      type: object
      properties:
        pay_now:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: The only amount Jinko charges at checkout.
        due_at_desk:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: Collected by the rental desk locally, in local currency.
                Display-only.
        estimated_total:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: pay_now + due_at_desk, where both are known.
        deposit:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: Security hold taken at the desk, not a charge.
    CarDriverAgeRange:
      type: object
      properties:
        min:
          type: integer
          example: 25
        max:
          type: integer
          example: 75
      description: The age band this price was quoted for, as the supplier states it.
        A driver outside the band is refused at the counter.
    CarCancellationFee:
      type: object
      properties:
        type:
          type: string
          example: cancellation
        fee:
          $ref: "#/components/schemas/CarAmount"
        non_refundable:
          type: boolean
        applicable_from:
          type: string
        applicable_to:
          type: string
        applicable_now:
          type: boolean
        seconds_before_pick_up:
          type: number
    CarOffer:
      type: object
      properties:
        trip_item_token:
          type: string
          description: The trip item token. Pass verbatim to POST /v1/trip as
            `add_item.trip_item_token` to add this rental to a trip.
          example: car_9f3b2a17c4e8d501
        offer_id:
          type: string
          description: "Deprecated: use `trip_item_token` instead. Same value."
          example: car_9f3b2a17c4e8d501
          deprecated: true
        vehicle:
          $ref: "#/components/schemas/CarVehicle"
        package:
          $ref: "#/components/schemas/CarPackage"
        pick_up:
          $ref: "#/components/schemas/CarBranch"
        drop_off:
          $ref: "#/components/schemas/CarBranch"
        price:
          $ref: "#/components/schemas/CarOfferPrice"
        driver_age_range:
          $ref: "#/components/schemas/CarDriverAgeRange"
        on_request:
          type: boolean
          description: The supplier confirms availability after booking rather than
            instantly.
        cancellation_fees:
          type: array
          items:
            $ref: "#/components/schemas/CarCancellationFee"
          description: Fee tiers by time before pick-up. An EMPTY list means the schedule
            is unknown — never render it as free cancellation.
        expires_at:
          type: string
          description: When the trip_item_token stops being addable to a trip. Re-search
            after this.
          example: "2026-09-12T10:30:00Z"
      required:
        - trip_item_token
        - offer_id
    CarResolvedPlace:
      type: object
      properties:
        name:
          type: string
          example: Lyon City Centre
        kind:
          type: string
          description: One of "airport", "railway", "port" or "bus" — absent for a
            city-centre rental office.
          example: airport
        city:
          type: string
          example: Lyon
        country:
          type: string
          example: FR
      description: How a free-text `place` was interpreted. Echoed so the caller can
        confirm the resolution.
    CarSearchResponse:
      type: object
      properties:
        offers:
          type: array
          items:
            $ref: "#/components/schemas/CarOffer"
        currency:
          type: string
          example: EUR
        resolved_place:
          $ref: "#/components/schemas/CarResolvedPlace"
        candidates:
          type: array
          items:
            $ref: "#/components/schemas/CarResolvedPlace"
          description: Returned instead of offers when a free-text `place` is ambiguous.
            Retry with `place` set to a candidate's `name`; when two candidates
            share a name, qualify it with the city — `"City Centre, Lyon"`.
        warnings:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
              message:
                type: string
    CarGeo:
      type: object
      properties:
        latitude:
          type: number
          minimum: -90
          maximum: 90
          example: 45.7256
        longitude:
          type: number
          minimum: -180
          maximum: 180
          example: 5.0811
        range:
          type: integer
          minimum: 50
          description: Search radius around the coordinates, in metres (minimum 50).
          example: 5000
      required:
        - latitude
        - longitude
        - range
      description: "Coordinates + radius. Searches the closest rental branches. Geo
        search is round-trip only: `drop_off` must be omitted or name the same
        place."
    CarPickUp:
      type: object
      properties:
        date_time:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$
          description: Pick-up date-time, branch-local, no timezone.
          example: "2026-09-12T10:00:00"
        airport_code:
          type: string
          pattern: ^[A-Za-z]{3}$
          description: IATA airport code.
          example: LYS
        place:
          type: string
          minLength: 1
          description: Free-text location — a city, district or landmark. Resolved
            server-side; when the text is ambiguous the response carries
            `candidates` instead of offers — retry with a candidate's `name`.
          example: Lyon city centre
        geo:
          $ref: "#/components/schemas/CarGeo"
      required:
        - date_time
    CarDropOff:
      type: object
      properties:
        date_time:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$
          description: Drop-off date-time, branch-local. May instead be given as the
            top-level `drop_off_date_time`.
        airport_code:
          type: string
          pattern: ^[A-Za-z]{3}$
          description: IATA airport code.
          example: LYS
        place:
          type: string
          minLength: 1
          description: Free-text location — a city, district or landmark. Resolved
            server-side; when the text is ambiguous the response carries
            `candidates` instead of offers — retry with a candidate's `name`.
          example: Lyon city centre
        geo:
          $ref: "#/components/schemas/CarGeo"
      description: Where the car is returned. Omit for a round trip (return to the
        pick-up branch) and set `drop_off_date_time` instead.
    CarSearchRequest:
      type: object
      properties:
        pick_up:
          $ref: "#/components/schemas/CarPickUp"
        drop_off:
          $ref: "#/components/schemas/CarDropOff"
        drop_off_date_time:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$
          description: Drop-off date-time for a round trip, branch-local. Required when
            `drop_off` is omitted.
          example: "2026-09-15T10:00:00"
        driver_age:
          type: integer
          minimum: 18
          maximum: 99
          description: Driver's age at pick-up (18-99). Pricing and availability are
            age-dependent.
          example: 30
        residence_country:
          type: string
          pattern: ^[A-Za-z]{2}$
          description: Driver's country of residence, ISO 3166-1 alpha-2. Rates and
            inclusions vary by residence.
          example: FR
        currency:
          type: string
          minLength: 3
          maxLength: 3
          description: ISO 4217 display currency. Defaults to USD.
          example: EUR
        lang:
          type: string
          description: BCP-47 language tag for vehicle and branch text.
          example: en-gb
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - pick_up
        - driver_age
        - residence_country
      description: "`pick_up` names exactly one of `airport_code`, `place` or `geo`,
        and a drop-off time must come from `drop_off.date_time` or
        `drop_off_date_time`. These rules are enforced at runtime but cannot be
        expressed in JSON Schema, so they do not appear in `required`."
      example:
        pick_up:
          airport_code: LYS
          date_time: "2026-09-12T10:00:00"
        drop_off_date_time: "2026-09-15T10:00:00"
        driver_age: 30
        residence_country: FR
        currency: EUR
    CarCancelPreviewResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: This preview’s quote. Pass it as `quote_id` to car_cancel_commit —
            it binds the commit to the fee quoted here. Treat as an opaque
            string; the format may evolve.
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
        cancellation_id:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
          deprecated: true
        cancellable:
          type: boolean
          example: true
        fee_known:
          type: boolean
          description: false means the fee could not be established — UNKNOWN, not free.
            Render as "we will confirm the fee".
          example: true
        fee_type:
          type: string
          example: cancellation
        fee:
          $ref: "#/components/schemas/CarAmount"
        paid:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: What the customer originally paid.
        refund_amount:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: paid minus fee. Absent whenever the fee is unknown — absent is not
                zero.
        currency:
          type: string
          example: EUR
        non_refundable:
          type: boolean
        refund_pending_review:
          type: boolean
          description: true means the refund figure is right but will be issued by hand
            rather than automatically (the rental was changed after it was paid
            for). The cancellation itself still goes through online; not a
            failure.
        refund_review_reason:
          type: string
          description: "Why a person is involved, whenever `manual_required` or
            `refund_pending_review` is true, in words the customer can be shown.
            Where the reason would be the supplier’s own words — as on a
            `cancellable: false` preview of a rental that cannot be cancelled at
            all — it reads “This request needs manual handling by Jinko
            support.”"
          example: the cancellation fee for this rental could not be established; a person
            will complete the cancellation
        manual_required:
          type: boolean
          description: "true means this cancellation cannot be completed online — the fee
            could not be established, the rental was changed after it was paid
            for, or the fee is in another currency or above the rental.
            `cancellable` is false, no refund figure is given and
            `refund_review_reason` says why. It is not a dead end:
            car_cancel_commit takes this `cancellation_id` with `manual_ok:
            true`, which records the cancellation for a Jinko agent to complete
            and answers `state: pending` with `refund_pending_review: true`.
            Without the flag such a commit is refused 409 `manual_required`, so
            a customer is never put in an agent queue unasked. Absent (or false)
            on every quote that can be committed online."
          example: false
        expires_at:
          type: string
          description: When this preview stops being committable (RFC 3339). A commit
            after it is refused 409 `QUOTE_EXPIRED`; preview again. Absent where
            the quote carries no deadline.
          example: "2026-09-21T10:15:00Z"
    CarServicingConflictCode:
      type: string
      enum:
        - quote_drift
        - QUOTE_EXPIRED
        - active_operation_exists
        - not_cancellable
        - funds_unavailable
        - manual_required
      description: "Which refusal this is. `manual_required` — the preview said
        `manual_required: true` (fee unknown, rental changed after payment, fee
        in another currency or above the rental) and the commit did not carry
        `manual_ok: true`; resend the same commit with it, once the customer
        agrees, to hand the cancellation to a Jinko agent. `quote_drift` — the
        refund moved since the preview (the fee tier changed as pick-up drew
        nearer); `retry_quote_id` is a fresh preview reference and
        `current.refund` the figure now — show it to the customer and commit
        against `retry_quote_id`. `QUOTE_EXPIRED` — the preview stopped binding
        (`expires_at`); preview again. `active_operation_exists` — an exchange
        or another cancellation is in flight for this rental; wait for it to
        finish (car_cancel_status) rather than starting a second.
        `not_cancellable` — the rental can no longer be cancelled as it stands
        (already cancelled since the preview, or over); `error.message` carries
        the reason, and car_cancel_status reports the cancellation that stands.
        `funds_unavailable` — the original payment cannot cover the refund yet;
        `shortfall` is how much is missing and `blocking` names the refunds that
        have to settle first. In every case NOTHING was cancelled and no money
        moved."
    CarServicingConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          $ref: "#/components/schemas/CarServicingConflictCode"
        retry_quote_id:
          type: string
          description: A fresh `quote_id`, on `quote_drift`. Show the customer the figure
            in `current.refund`, then commit against this `quote_id` as you
            would one from car_cancel_preview.
          example: ccl_01J8AB4N7GLY3Q0DXK2M5R9VWT
        requote:
          type: string
          description: "Deprecated: use `retry_quote_id` instead. Same value."
          example: ccl_01J8AB4N7GLY3Q0DXK2M5R9VWT
          deprecated: true
        current:
          type: object
          properties:
            refund:
              $ref: "#/components/schemas/CarAmount"
          description: "The refund as it stands now, on `quote_drift`: what the customer
            gets if they accept the fresh preview."
        active_operation:
          type: string
          description: The cancellation already running on this rental, on
            `active_operation_exists`. Follow it with car_cancel_status.
          example: ccl_01J7ZR5Q2KME8V4TBN3P8XD6WQ
        shortfall:
          allOf:
            - $ref: "#/components/schemas/CarAmount"
            - description: How much of the refund could not be reserved, on
                `funds_unavailable` — money still moving on the original
                payment, not a fact about this rental.
        blocking:
          type: array
          items:
            type: string
          description: "What is holding that money, on `funds_unavailable`: the refunds
            already in flight against the same payment, which settle before this
            one can be reserved. Opaque handles — identity only."
          example:
            - re_3UBIxK2eZvKYlo2C
      required:
        - error
        - code
    BookingItemServicing:
      type: object
      properties:
        can_refund:
          type: boolean
        can_void:
          type: boolean
        can_exchange:
          type: boolean
        refund_support_level:
          type: string
          enum: &a23
            - AUTO
            - MANUAL_REQUIRED
            - UNSUPPORTED
        exchange_support_level:
          type: string
          enum: *a23
        refund_unavailable_reason:
          type: string
        exchange_unavailable_reason:
          type: string
        refund_reason_code:
          type: string
        exchange_reason_code:
          type: string
        reason_code:
          type: string
        support_level:
          type: string
          enum: *a23
      required:
        - can_refund
        - can_void
        - can_exchange
      description: Eligibility of this booked item and its current product. Read the
        live refund or exchange check before committing; eligibility can change
        with time.
    BookingItem:
      type: object
      properties:
        booked_item_id:
          type: string
          description: The item to name with `booked_item_id` on the next request.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        item_id:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: "Deprecated: use `booked_item_id` instead. The booked item as an
            integer."
          example: 42
          deprecated: true
        domain:
          type: string
        summary:
          type: string
        status:
          type: string
          description: "This item's state in Jinko's own booking and servicing flow. In
            progress: `pending`, `awaiting_payment`, `preparing`, `prepared`,
            `processing`, `confirming`. Final: `completed` (booked; for a
            flight, ticketed), `failed`, `cancelled` (nothing is booked any
            more: the checkout was never paid, or a cancellation succeeded),
            `expired_quote` (a quoted price, at checkout or for an exchange,
            expired before it was confirmed). Needing attention:
            `exchange_partial_failure`, `needs_review`. Treat the list as open:
            new values may be added. It changes only through Jinko's steps
            (payment, booking, ticketing, or a cancellation or exchange you
            request), never because an airline changed or cancelled a flight."
          example: completed
        booking_ref:
          type: string
          description: The Jinko booking reference of the booking this item belongs to,
            also after an exchange.
          example: JNK-A0AUR2
        booking_reference:
          type: string
          description: "Deprecated: use `booking_ref` instead. The Jinko reference of the
            cart this item lives on: after an exchange, the exchange’s own
            reference."
          deprecated: true
        servicing:
          $ref: "#/components/schemas/BookingItemServicing"
      required:
        - item_id
        - domain
    BookingSelectionConflict:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - CONFLICT
            message:
              type: string
          required:
            - code
            - message
        code:
          type: string
          enum:
            - item_selection_required
        items:
          type: array
          items:
            $ref: "#/components/schemas/BookingItem"
      required:
        - error
        - code
        - items
      description: Several items match the requested domain. Choose a booked_item_id
        from items (the same safe projection as get_booking) and repeat the
        request with booking_ref and booked_item_id.
    CarCancelPreviewRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - booking_ref
      example: &a24
        booking_ref: JNK-8PT9VS
        last_name: Doe
    CarCancelCommitResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: The quote this cancellation was committed against.
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
        cancellation_id:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
          deprecated: true
        state:
          type: string
          description: "`confirmed` — cancelled and the refund issued or on its way.
            `pending` — recorded but not finished: the platform is still
            completing it, or (with `refund_pending_review: true`) a Jinko agent
            has it; read car_cancel_status, do not commit again. `rejected` —
            the rental company declined; the booking still stands and
            `rejected_reason` says why. `failed` — the attempt did not complete;
            read car_cancel_status before trying again."
          example: confirmed
        fee_known:
          type: boolean
        fee:
          $ref: "#/components/schemas/CarAmount"
        paid:
          $ref: "#/components/schemas/CarAmount"
        refund_amount:
          $ref: "#/components/schemas/CarAmount"
        refund_pending_review:
          type: boolean
          description: "true means the booking IS cancelled (or, with `state: pending`,
            recorded for a Jinko agent) but the refund needs a person before it
            is issued — do not quote `refund_amount` as final."
        stripe_refund_id:
          type: string
          description: Deprecated. An internal payment reference.
          deprecated: true
        rejected_reason:
          type: string
        completed_at:
          type: string
          example: "2026-08-20T15:18:00Z"
    CarCancelCommitRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        intent:
          $ref: "#/components/schemas/IntentInput"
        quote_id:
          type: string
          minLength: 1
          description: The `quote_id` from a preceding car_cancel_preview. Binds the
            commit to the fee the customer saw.
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
        reason:
          type: string
          description: Optional free-text cancellation reason.
          example: Change of plans
        manual_ok:
          type: boolean
          description: "Send `true` to commit a preview that answered `manual_required:
            true`. The cancellation is then recorded for a Jinko agent — NOTHING
            is sent to the rental company by this call — and the answer is
            `state: pending` with `refund_pending_review: true`; the agent
            completes it and settles the refund by hand, and car_cancel_status
            reports the outcome. Without the flag such a commit is refused 409
            `manual_required`, so a customer is never put in an agent queue
            unasked: send it only once the customer has agreed to that. On a
            preview that can be committed online the flag changes nothing."
          example: false
      required:
        - booking_ref
        - quote_id
      example:
        booking_ref: JNK-8PT9VS
        last_name: Doe
        quote_id: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
    CarCancelStatusResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: The quote this cancellation was committed against.
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
        cancellation_id:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: ccl_2f7c9a4e8b1d4c6f9e3a5b7d1c2e4f6a
          deprecated: true
        state:
          type: string
          description: "The same words as car_cancel_commit: `preview` (quoted, never
            committed), `pending` (recorded, not finished — the platform or a
            Jinko agent still has it), `confirmed`, `rejected`, `failed`."
          example: confirmed
        fee_known:
          type: boolean
        fee:
          $ref: "#/components/schemas/CarAmount"
        paid:
          $ref: "#/components/schemas/CarAmount"
        refund_amount:
          $ref: "#/components/schemas/CarAmount"
        refund_pending_review:
          type: boolean
        stripe_refund_id:
          type: string
          description: Deprecated. An internal payment reference.
          deprecated: true
        rejected_reason:
          type: string
    CarCancelStatusRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - booking_ref
      example: *a24
    DestinationSnapshotRow:
      type: object
      properties:
        rank:
          type: number
          example: 1
        destination:
          type: string
          example: City:PAR
        share:
          type: number
          example: 0.182
    DestinationResponse:
      type: object
      properties:
        rows:
          type: array
          items:
            $ref: "#/components/schemas/DestinationSnapshotRow"
      required:
        - rows
    MarketSnapshotRow:
      type: object
      properties:
        rank:
          type: number
          example: 1
        market:
          type: string
          example: Country:US
        share:
          type: number
          example: 0.214
    MarketResponse:
      type: object
      properties:
        rows:
          type: array
          items:
            $ref: "#/components/schemas/MarketSnapshotRow"
      required:
        - rows
    AudienceSnapshotRow:
      type: object
      properties:
        rank:
          type: number
          example: 1
        audience:
          type: string
          example: Couple
        share:
          type: number
          example: 0.37
    AudienceResponse:
      type: object
      properties:
        rows:
          type: array
          items:
            $ref: "#/components/schemas/AudienceSnapshotRow"
      required:
        - rows
    TrendSeries:
      type: object
      properties:
        label:
          type: string
          description: Dimension value for ranked endpoints.
          example: FR
        origin:
          type: string
          example: Country:US
        destination:
          type: string
          example: Country:FR
        series:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
                example: "2026-06-20"
              value:
                type: number
                example: 1234
            required:
              - date
              - value
        summary:
          type: object
          properties:
            total:
              type: number
              example: 34567
            avg_per_day:
              type: number
              example: 1191
            growth_pct:
              type: number
              nullable: true
              example: 12.3
            peak_date:
              type: string
              example: "2026-06-14"
            peak_value:
              type: number
              example: 1890
      required:
        - series
    TrendResponse:
      type: object
      properties:
        granularity:
          type: string
          example: week
        from:
          type: string
          example: "2026-06-19"
        to:
          type: string
          example: "2026-06-25"
        series:
          type: array
          items:
            $ref: "#/components/schemas/TrendSeries"
      required:
        - granularity
        - from
        - to
        - series
    ItemExchangeView:
      type: object
      properties:
        state:
          type: string
          description: "`attention_required` when the request is with Jinko support;
            `in_progress` when support is completing it; `succeeded` when
            completed; `failed` when support closed it."
          example: attention_required
        operation:
          type: string
          description: The operation is `exchange`.
          example: exchange
        reason:
          type: string
        park_deadline:
          type: string
        next_run_at:
          type: string
        paid:
          $ref: "#/components/schemas/Money"
        refund_due:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: What the operation says the customer is owed.
            penalty:
              $ref: "#/components/schemas/Money"
            source:
              type: string
              description: "Where the figure came from: `quoted` (what the platform expects)
                or `provider_confirmed` (what the supplier agreed to)."
              example: quoted
        refunded:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: What was refunded, as read back from the payment provider.
            at:
              type: string
              example: "2026-09-03T12:30:00Z"
            stripe_reference:
              type: string
              description: Deprecated. An internal payment reference.
              example: re_3UBIxK2eZvKYlo2C
              deprecated: true
      description: An exchange Jinko support handles by hand. Present only when the
        item has such a request; absent otherwise. `operation` is `exchange`.
        State `attention_required` means the request is with Jinko support and
        `refund_due` is the quoted refund; `in_progress` means support is
        completing it; `succeeded` means completed and `refunded` says what was
        refunded and when; `failed` means support closed the request. Hidden
        while the item has a cancellation (`cancellation.state` other than
        `none`).
    SeatRefund:
      type: object
      properties:
        offer_id:
          type: string
        seat_number:
          type: string
          example: 12B
        traveler_ref:
          type: string
          example: pax_1
        pax_ref_id:
          type: string
          description: "Deprecated: use `traveler_ref` instead. Same value."
          example: pax_1
          deprecated: true
        status:
          type: string
          enum:
            - pending_airline_refund
            - refunded
            - not_refunded
        amount:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The seat price while pending, then the actual customer refund
                amount (zero when not refunded). Not part of the separate quoted
                fare refund.
        carrier:
          type: string
          description: Airline display name.
          example: United
        message:
          type: string
          description: Customer-facing sentence explaining the seat refund.
          example: Your paid seat will be refunded once United refunds Jinko.
        airline_refund_registered:
          type: boolean
          description: Whether the airline refund has been registered with the payment
            provider.
      required:
        - offer_id
        - seat_number
        - status
        - amount
        - carrier
        - message
        - airline_refund_registered
      description: A carrier-settled paid seat is refunded once the airline refunds
        Jinko. It is not part of the quoted fare refund; track its separate
        status here.
    BookedAncillary:
      type: object
      properties:
        type:
          type: string
          enum:
            - seat
            - bag
            - meal
            - cabin_bag_upgrade
            - sports_equipment
            - priority_boarding
            - assistance
            - insurance
            - lounge
            - frequent_flyer
            - other
          description: "What was booked: a seat, a bag, a meal or another service. Treat
            the list as open: new kinds may be added."
          example: seat
        seat_number:
          type: string
          example: 12B
        traveler_ref:
          type: string
          example: pax_1
        pax_ref_id:
          type: string
          description: "Deprecated: use `traveler_ref` instead. Same value."
          example: pax_1
          deprecated: true
        segment_ref_ids:
          type: array
          items:
            type: string
          example:
            - seg_1
        status:
          type: string
          enum:
            - confirmed
            - pending
            - failed
          description: For seats, `pending` means the airline has not confirmed the seat
            yet. `confirmed` means booked with the airline. `failed` means not
            booked.
        not_charged:
          type: boolean
          description: true when this seat is not charged to the traveler.
        failure_reason:
          type: string
          nullable: true
          description: Public partner-facing explanation of a failed or unresolved
            outcome; never internal diagnostics.
        price:
          $ref: "#/components/schemas/Money"
        refund:
          $ref: "#/components/schemas/SeatRefund"
      required:
        - type
        - status
      description: "An ancillary selected for this booked item: a seat, a bag, a meal
        or another service. `seat_number` is set on a seat. Price is omitted for
        an included or free ancillary; otherwise it uses the item confirmation’s
        total_paid money shape, in the trip currency. Booking payment totals are
        unchanged by this list."
    BookingFlightSegment:
      type: object
      properties:
        airline:
          type: string
          description: Marketing carrier code.
        airline_name:
          type: string
          description: Marketing carrier name.
        airline_logo:
          type: string
          description: Marketing carrier logo URL.
        flight_number:
          type: string
          description: Flight number without the carrier code.
          example: "57"
        operating_carrier:
          type: string
          description: Operating carrier code.
        operating_carrier_info:
          type: object
          properties:
            code:
              type: string
            name:
              type: string
            logo:
              type: string
        aircraft:
          type: string
          example: "777"
        departure_airport:
          type: string
        departure_city:
          type: string
        departure_city_name:
          type: string
        arrival_airport:
          type: string
        arrival_city:
          type: string
        arrival_city_name:
          type: string
        departure_time:
          type: string
          description: The scheduled time as booked, in the airport's local time with its
            UTC offset (RFC 3339), e.g. `2026-11-27T18:05:00-05:00`. Without an
            offset when the airport's time zone is unknown.
          example: "2026-11-27T18:05:00-05:00"
        arrival_time:
          type: string
          description: The scheduled time as booked, in the airport's local time with its
            UTC offset (RFC 3339), e.g. `2026-11-27T18:05:00-05:00`. Without an
            offset when the airport's time zone is unknown.
          example: "2026-11-28T07:25:00+01:00"
        departure_time_local:
          type: string
          description: The same wall-clock time without an offset (`YYYY-MM-DDTHH:MM:SS`).
          example: "2026-11-27T18:05:00"
        arrival_time_local:
          type: string
          description: The same wall-clock time without an offset (`YYYY-MM-DDTHH:MM:SS`).
          example: "2026-11-28T07:25:00"
        duration_minutes:
          type: integer
        layover_minutes:
          type: integer
          description: Minutes on the ground after this segment, before the next one
            departs; absent on the last segment of a journey.
      description: A flight segment as booked and ticketed. No terminal and no
        per-segment status are given.
    BookingFlightJourney:
      type: object
      properties:
        origin:
          type: string
        origin_name:
          type: string
        origin_airport_name:
          type: string
        destination:
          type: string
        destination_name:
          type: string
        destination_airport_name:
          type: string
        departure_datetime:
          type: string
          description: First departure of the journey. The scheduled time as booked, in
            the airport's local time with its UTC offset (RFC 3339), e.g.
            `2026-11-27T18:05:00-05:00`. Without an offset when the airport's
            time zone is unknown.
          example: "2026-11-27T18:05:00-05:00"
        arrival_datetime:
          type: string
          description: Final arrival of the journey. The scheduled time as booked, in the
            airport's local time with its UTC offset (RFC 3339), e.g.
            `2026-11-27T18:05:00-05:00`. Without an offset when the airport's
            time zone is unknown.
          example: "2026-11-28T07:25:00+01:00"
        duration_minutes:
          type: integer
        stops:
          type: integer
        stop_infos:
          type: array
          items:
            type: object
            properties:
              airport_code:
                type: string
              duration_minutes:
                type: integer
        airline:
          type: string
        airline_name:
          type: string
        airline_logo:
          type: string
        segments:
          type: array
          items:
            $ref: "#/components/schemas/BookingFlightSegment"
      description: One journey of the booked and ticketed itinerary, with its flight
        segments in flown order.
    BookingFlightDetails:
      type: object
      properties:
        pnr:
          type: string
          description: "Deprecated: use `supplier_references` instead. The validating
            carrier’s record locator; when it is not known, an id only Jinko’s
            intermediary answers to."
          deprecated: true
        ticket_numbers:
          type: array
          items:
            type: string
          description: The ticket numbers issued for this item. Absent when none is
            recorded.
          example:
            - "0010000000001"
            - "0010000000002"
        airline_locators:
          type: array
          items:
            type: object
            properties:
              carrier_code:
                type: string
              carrier_name:
                type: string
              locator:
                type: string
          description: "Deprecated: use `supplier_references` instead. Each airline's own
            record locator, one per carrier; the item's `supplier_references`
            lists the same locators."
          deprecated: true
        trip_type:
          type: string
          description: "The itinerary shape: `one_way`, `round_trip`, `open_jaw` or
            `multi_city`. Absent on a booking confirmed before it was recorded."
          example: round_trip
        origin_city_code:
          type: string
        destination_city_code:
          type: string
        cabin_class:
          type: string
        validating_carrier:
          type: string
        validating_carrier_info:
          type: object
          properties:
            code:
              type: string
            name:
              type: string
            logo:
              type: string
        legs:
          type: array
          items:
            $ref: "#/components/schemas/BookingFlightJourney"
          description: "Every journey of the itinerary in flown order, as booked and
            ticketed. It is not refreshed from the airline afterwards: a
            schedule change or cancellation made by the airline is not reflected
            here. Absent on a booking confirmed before legs were recorded. After
            an exchange that re-issued part of the itinerary it holds the
            re-issued journeys only, so read `trip_type` rather than counting
            legs."
        outbound_flight:
          $ref: "#/components/schemas/BookingFlightJourney"
        inbound_flight:
          $ref: "#/components/schemas/BookingFlightJourney"
        refund_policy:
          type: string
        change_policy:
          type: string
        carry_on_baggage:
          type: string
        checked_baggage:
          type: string
      description: Flight confirmation details as booked and ticketed.
        `outbound_flight` and `inbound_flight` are `legs[0]` and `legs[1]` under
        older names; `inbound_flight` is the second journey, not necessarily a
        return.
    BookingHotelDetails:
      type: object
      properties:
        hotel_id:
          type: string
          example: lp1d2c3
        hotel_name:
          type: string
          example: NH Paris Opéra Faubourg
        address:
          type: string
        star_rating:
          type: integer
          example: 4
        main_photo_url:
          type: string
        check_in:
          type: string
          example: "2026-11-15"
        check_out:
          type: string
          example: "2026-11-17"
        num_nights:
          type: integer
          example: 2
        room_name:
          type: string
          example: Standard Double
        room_description:
          type: string
        max_occupancy:
          type: integer
          example: 2
        board_type:
          type: string
          description: The board code of the meal plan the guest bought, as the rate sold
            it — the same value the trip item’s `hotel_terms.board_type` stated
            at checkout (`RO` room only, `BB` bed and breakfast, `HB` half
            board, …; some suppliers use `BI` for breakfast included). On a
            multi-room booking, present only when every room is on the same
            board; read `rooms[].board_type` otherwise. Absent on bookings
            confirmed before the meal plan was recorded.
          example: BI
        board_name:
          type: string
          description: The meal plan the guest bought, in words, as the rate sold it — the
            same value the trip item’s `hotel_terms.board_name` stated at
            checkout. On a multi-room booking the rooms’ distinct boards joined
            with "; ". Absent on bookings confirmed before the meal plan was
            recorded.
          example: Breakfast Included
        is_refundable:
          type: boolean
          example: true
        cancellation_summary:
          type: string
        free_cancellation_until:
          type: string
        hotel_confirmation_number:
          type: string
          description: "Deprecated: use `supplier_references` instead. The hotel’s own
            confirmation number, once the property issued one."
          deprecated: true
        rooms:
          type: array
          items:
            type: object
            properties:
              room_number:
                type: integer
                example: 1
              room_name:
                type: string
                example: Twin Room
              board_type:
                type: string
                example: BB
              board_name:
                type: string
                example: BED AND BREAKFAST
              is_refundable:
                type: boolean
              cancellation_summary:
                type: string
              free_cancellation_until:
                type: string
          description: Each room of a multi-room booking with its own meal plan and
            cancellation terms, in room order. Absent on a single-room booking.
      description: "The stay a booked hotel item confirms: the property, the dates,
        the room, the meal plan the guest bought (`board_type`, `board_name`)
        and the cancellation terms read at checkout. The platform sends more and
        all of it reaches you."
    Booking:
      type: object
      properties:
        booking_ref:
          type: string
          description: The Jinko booking reference of this booking. Looked up with the
            reference of one of its exchanges, it is still the booking’s own
            reference. Hand it to cancel, refund and exchange as `booking_ref`.
          example: JNK-XEVGW5
        booking_reference:
          type: string
          description: "Deprecated: use `booking_ref` instead. The reference the booking
            was looked up with, which can be an exchange’s own reference."
          example: JNK-XEVGW5
          deprecated: true
        booking_state:
          type: string
          enum: *a25
          description: "The booking’s progress once payment has started; absent before.
            `awaiting_payment`: waiting for the payment to be confirmed.
            `processing`: booking with the suppliers. Then one outcome:
            `completed` (every item booked), `partial` (some items booked),
            `failed` (nothing booked) or `cancelled`. `needs_review`: held for a
            person at Jinko to resolve; not final. `fulfillment.status` keeps
            the detailed status behind it."
          example: completed
        status:
          type: string
          description: "The booking's state in Jinko's own booking and servicing flow. In
            progress: `pending`, `awaiting_payment`, `preparing`, `prepared`,
            `processing`, `confirming`. Final: `completed` (booked; for a
            flight, ticketed), `partial` (some items booked, others failed),
            `failed`, `cancelled` (nothing is booked any more: the checkout was
            never paid, or every item was cancelled), `expired_quote` (a quoted
            price, at checkout or for an exchange, expired before it was
            confirmed). Needing attention: `exchange_partial_failure`,
            `needs_review`. Treat the list as open: new values may be added. It
            changes only through Jinko's steps (payment, booking, ticketing, or
            a cancellation or exchange you request), never because an airline
            changed or cancelled a flight."
          example: completed
        failure_reason:
          type: string
          nullable: true
          description: "Why the booking failed, when it failed after payment and the cause
            is known: `offer_unavailable`, `price_changed`,
            `booking_not_created` (the supplier holds no booking; nothing was
            booked and no money was taken), `booking_cancelled_at_provider`,
            `ticketing_refused`. Null otherwise. For `offer_unavailable`, the
            supplier no longer sells the priced offer. Nothing was booked and
            the card authorisation was released. Search again and book a new
            offer. The `booking.failed` webhook carries the same reason with a
            sentence to show the traveller (`failure_message`)."
          example: booking_not_created
        type:
          type: string
          description: What was booked — "flight" or "hotel".
          example: flight
        last_name:
          type: string
          example: Doe
        total_paid:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "What was captured for this booking, gross: refunds are NOT
                subtracted (the same figure as `paid` in `servicing_summary`;
                `net_paid` there is the figure after refunds). Absent when the
                captured amount is unknown, and when the booking was charged in
                more than one currency — read `servicing_summary`, one row per
                currency, then."
        refund_status:
          type: object
          properties:
            state:
              type: string
              description: "`in_progress`, `succeeded` or `failed`."
              example: succeeded
            initiated_at:
              type: string
            completed_at:
              type: string
            refunded_amount:
              $ref: "#/components/schemas/Money"
        servicing_summary:
          type: array
          items:
            type: object
            properties:
              currency:
                type: string
                example: USD
              paid:
                $ref: "#/components/schemas/Money"
              refunded:
                $ref: "#/components/schemas/Money"
              net_paid:
                $ref: "#/components/schemas/Money"
              attention_required:
                type: boolean
            description: One currency’s servicing totals. `paid` includes the original
              charge as well as money collected for exchanges (settled
              ADD_COLLECT collections). `attention_required` is true on the
              booking currency’s row while a manual exchange case is open.
        items:
          type: array
          items:
            allOf:
              - $ref: "#/components/schemas/BookingItem"
              - type: object
                properties:
                  booking_ref:
                    type: string
                    description: "The Jinko booking reference of the booking this item belongs to:
                      the same value as the booking’s `booking_ref`, also after
                      an exchange."
                    example: JNK-XEVGW5
                  servicing:
                    allOf:
                      - $ref: "#/components/schemas/BookingItemServicing"
                      - type: object
                        properties:
                          cancellation:
                            type: object
                            properties:
                              state:
                                type: string
                                description: "`none` when nothing has cancelled the item; otherwise
                                  `in_progress`, `attention_required`,
                                  `succeeded` or `failed`."
                                example: succeeded
                              operation:
                                type: string
                                example: svc_01J7ZR5Q2KME8V4T
                              reason:
                                type: string
                              park_deadline:
                                type: string
                              next_run_at:
                                type: string
                              paid:
                                $ref: "#/components/schemas/Money"
                              refund_due:
                                type: object
                                properties:
                                  amount:
                                    type: number
                                    description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                                      some endpoints (the two never appear
                                      together); its scale depends on
                                      decimal_places. When this object carries
                                      decimal_places, amount is an INTEGER in
                                      minor units — divide by 10 **
                                      decimal_places (e.g. select_ancillaries
                                      total_with_ancillaries). When there is no
                                      decimal_places field, amount is a decimal
                                      in MAJOR units, safe to display as-is
                                      (e.g. trip and checkout totals)."
                                    deprecated: true
                                  value:
                                    type: integer
                                    description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                                      units, always paired with decimal_places —
                                      divide by 10 ** decimal_places to display.
                                      Example: value 15977 with decimal_places 2
                                      is 159.77 USD. Rendering this field
                                      directly shows prices 100x too high for
                                      2-decimal currencies."
                                    example: 41250
                                    deprecated: true
                                  currency:
                                    type: string
                                    description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
                                    example: USD
                                    deprecated: true
                                  decimal_places:
                                    type: integer
                                    description: "Deprecated: use `amount_money` instead. Scale of the integer
                                      value/amount: display = integer / 10 **
                                      decimal_places. Always sent alongside
                                      minor-unit amounts. Usually the ISO 4217
                                      digits of the currency (2 for USD/EUR/GBP,
                                      0 for JPY/KRW, 3 for BHD/JOD/KWD) but
                                      currency-converted prices can carry a
                                      different scale — ALWAYS use the
                                      decimal_places sent with the amount, never
                                      a hardcoded 2. Only if the field is
                                      genuinely absent on a value-shaped object,
                                      fall back to the ISO digits for the
                                      currency."
                                    example: 2
                                    deprecated: true
                                  display:
                                    type: string
                                    description: 'Deprecated: use `amount_money` instead. The same figure as a
                                      string ready to show: the ISO 4217 code, a
                                      space, then the amount, e.g. "USD 159.77".
                                      With decimal_places it is written at
                                      exactly that scale (value 1561500, JPY,
                                      decimal_places 2 is "JPY 15615.00");
                                      without, at the ISO digits of the
                                      currency. Show this; compute with the
                                      number. Absent when the figure is not
                                      money (a cancellation step expressed as a
                                      percent or a number of nights) or could
                                      not be read unambiguously.'
                                    example: USD 412.50
                                    deprecated: true
                                  amount_money:
                                    allOf:
                                      - $ref: "#/components/schemas/MoneyValue"
                                      - description: What the operation says the customer is owed.
                                  penalty:
                                    $ref: "#/components/schemas/Money"
                                  source:
                                    type: string
                                    description: "Where the figure came from: `quoted` (what the platform expects)
                                      or `provider_confirmed` (what the supplier
                                      agreed to)."
                                    example: quoted
                              refunded:
                                type: object
                                properties:
                                  amount:
                                    type: number
                                    description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                                      some endpoints (the two never appear
                                      together); its scale depends on
                                      decimal_places. When this object carries
                                      decimal_places, amount is an INTEGER in
                                      minor units — divide by 10 **
                                      decimal_places (e.g. select_ancillaries
                                      total_with_ancillaries). When there is no
                                      decimal_places field, amount is a decimal
                                      in MAJOR units, safe to display as-is
                                      (e.g. trip and checkout totals)."
                                    deprecated: true
                                  value:
                                    type: integer
                                    description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                                      units, always paired with decimal_places —
                                      divide by 10 ** decimal_places to display.
                                      Example: value 15977 with decimal_places 2
                                      is 159.77 USD. Rendering this field
                                      directly shows prices 100x too high for
                                      2-decimal currencies."
                                    example: 41250
                                    deprecated: true
                                  currency:
                                    type: string
                                    description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
                                    example: USD
                                    deprecated: true
                                  decimal_places:
                                    type: integer
                                    description: "Deprecated: use `amount_money` instead. Scale of the integer
                                      value/amount: display = integer / 10 **
                                      decimal_places. Always sent alongside
                                      minor-unit amounts. Usually the ISO 4217
                                      digits of the currency (2 for USD/EUR/GBP,
                                      0 for JPY/KRW, 3 for BHD/JOD/KWD) but
                                      currency-converted prices can carry a
                                      different scale — ALWAYS use the
                                      decimal_places sent with the amount, never
                                      a hardcoded 2. Only if the field is
                                      genuinely absent on a value-shaped object,
                                      fall back to the ISO digits for the
                                      currency."
                                    example: 2
                                    deprecated: true
                                  display:
                                    type: string
                                    description: 'Deprecated: use `amount_money` instead. The same figure as a
                                      string ready to show: the ISO 4217 code, a
                                      space, then the amount, e.g. "USD 159.77".
                                      With decimal_places it is written at
                                      exactly that scale (value 1561500, JPY,
                                      decimal_places 2 is "JPY 15615.00");
                                      without, at the ISO digits of the
                                      currency. Show this; compute with the
                                      number. Absent when the figure is not
                                      money (a cancellation step expressed as a
                                      percent or a number of nights) or could
                                      not be read unambiguously.'
                                    example: USD 412.50
                                    deprecated: true
                                  amount_money:
                                    allOf:
                                      - $ref: "#/components/schemas/MoneyValue"
                                      - description: What was refunded, as read back from the payment provider.
                                  at:
                                    type: string
                                    example: "2026-09-03T12:30:00Z"
                                  stripe_reference:
                                    type: string
                                    description: Deprecated. An internal payment reference.
                                    example: re_3UBIxK2eZvKYlo2C
                                    deprecated: true
                          exchange:
                            $ref: "#/components/schemas/ItemExchangeView"
                    description: Eligibility of this booked item and its current product. Read the
                      live refund or exchange check before committing;
                      eligibility can change with time.
                  supplier_references:
                    type: array
                    items:
                      $ref: "#/components/schemas/SupplierReference"
                    description: "The confirmations the supplier itself issued for this item: one
                      per airline record locator, the hotel’s confirmation
                      number, the rental company’s confirmation. Empty when none
                      is known yet."
                  failure_reason:
                    type: string
                    nullable: true
                    description: "Why the booking failed, when it failed after payment and the cause
                      is known: `offer_unavailable`, `price_changed`,
                      `booking_not_created` (the supplier holds no booking;
                      nothing was booked and no money was taken),
                      `booking_cancelled_at_provider`, `ticketing_refused`. Null
                      otherwise. For `offer_unavailable`, the supplier no longer
                      sells the priced offer. Nothing was booked and the card
                      authorisation was released. Search again and book a new
                      offer. The `booking.failed` webhook carries the same
                      reason with a sentence to show the traveller
                      (`failure_message`)."
                    example: booking_not_created
                  booked_ancillaries:
                    type: array
                    items:
                      $ref: "#/components/schemas/BookedAncillary"
                  confirmation:
                    type: object
                    properties:
                      confirmation_number:
                        type: string
                        description: "Deprecated: use `supplier_references` instead. A confirmation
                          number for this item; when the airline’s own locator
                          is not known it can hold an id only Jinko’s
                          intermediary answers to."
                        deprecated: true
                      product_summary:
                        type: string
                      total_paid:
                        $ref: "#/components/schemas/Money"
                      details:
                        type: object
                        properties:
                          flight:
                            $ref: "#/components/schemas/BookingFlightDetails"
                          car:
                            type: object
                            properties:
                              due_at_desk:
                                $ref: "#/components/schemas/Money"
                              deposit:
                                $ref: "#/components/schemas/Money"
                              estimated_total:
                                $ref: "#/components/schemas/Money"
                              ancillaries:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    offer_id:
                                      type: string
                                    label:
                                      type: string
                                    quantity:
                                      type: integer
                                    paid_at:
                                      type: string
                                    price:
                                      $ref: "#/components/schemas/Money"
                              cancellation_fees:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    fee:
                                      $ref: "#/components/schemas/Money"
                                    non_refundable:
                                      type: boolean
                                    applicable_from:
                                      type: string
                                    applicable_to:
                                      type: string
                          hotel:
                            $ref: "#/components/schemas/BookingHotelDetails"
                  cancellation:
                    type: object
                    properties:
                      state:
                        type: string
                        example: confirmed
                      refund_method:
                        type: string
                      monetary_refund_minor:
                        type: integer
                        description: "Deprecated: use `monetary_refund_money` instead. The money refund
                          in minor units of `currency`, with no
                          `decimal_places`."
                        deprecated: true
                      voucher_refund_minor:
                        type: integer
                        description: "Deprecated: use `voucher_refund_money` instead. The voucher refund
                          in minor units of `currency`, with no
                          `decimal_places`."
                        deprecated: true
                      fee_minor:
                        type: integer
                        description: "Deprecated: use `fee_money` instead. The cancellation fee in minor
                          units of `currency`, with no `decimal_places`."
                        deprecated: true
                      currency:
                        type: string
                        description: "Deprecated: use `monetary_refund_money` instead. The currency of
                          the three `*_minor` figures; each `*_money` field
                          carries its own."
                        deprecated: true
                      monetary_refund_money:
                        allOf:
                          - $ref: "#/components/schemas/MoneyValue"
                          - description: The refund paid back as money.
                      voucher_refund_money:
                        allOf:
                          - $ref: "#/components/schemas/MoneyValue"
                          - description: The refund given as a supplier voucher.
                      fee_money:
                        allOf:
                          - $ref: "#/components/schemas/MoneyValue"
                          - description: The cancellation fee.
                      fee_known:
                        type: boolean
                  exchange:
                    type: object
                    properties:
                      exchange_ref:
                        type: string
                      state:
                        type: string
                      delta_direction:
                        type: string
                        description: "`add_collect`, `refund` or `even`: which way the difference
                          moves."
                        example: add_collect
                      delta_amount_minor:
                        type: integer
                        description: "Deprecated: use `delta_amount_money` instead. The absolute
                          difference in minor units of `currency`, with no
                          `decimal_places`."
                        deprecated: true
                      new_total_minor:
                        type: integer
                        description: "Deprecated: use `new_total_money` instead. The replacement rental
                          total in minor units of `currency`, with no
                          `decimal_places`."
                        deprecated: true
                      currency:
                        type: string
                        description: "Deprecated: use `delta_amount_money` instead. The currency of the
                          two `*_minor` figures; each `*_money` field carries
                          its own."
                        deprecated: true
                      delta_amount_money:
                        allOf:
                          - $ref: "#/components/schemas/MoneyValue"
                          - description: The ABSOLUTE difference between the old and the new rental;
                              `delta_direction` says which way it moves.
                      new_total_money:
                        allOf:
                          - $ref: "#/components/schemas/MoneyValue"
                          - description: The replacement rental’s total.
        can_refund:
          type: boolean
          description: OR aggregate over items[].servicing.can_refund; select an item
            before acting.
          deprecated: true
        can_void:
          type: boolean
          description: OR aggregate over items[].servicing.can_void; select an item before
            acting.
          deprecated: true
        can_exchange:
          type: boolean
          description: OR aggregate over items[].servicing.can_exchange; select an item
            before acting.
          deprecated: true
        refund_support_level:
          type: string
          enum:
            - AUTO
            - MANUAL_REQUIRED
            - UNSUPPORTED
          description: Use items[].servicing.refund_support_level.
          deprecated: true
        exchange_support_level:
          type: string
          enum:
            - AUTO
            - MANUAL_REQUIRED
            - UNSUPPORTED
          description: Use items[].servicing.exchange_support_level.
          deprecated: true
        created_at:
          type: string
          example: "2026-05-20T09:14:00Z"
        calendar:
          $ref: "#/components/schemas/BookingCalendar"
      description: "The booked trip. Minimally described — the platform sends more
        (items, per-item confirmations, provider state) and all of it reaches
        you. The two `*_support_level` fields are a SNAPSHOT: a fare’s void
        window closes with time, so before acting on a refund or exchange read
        the level from a live POST /v1/refund_check or POST /v1/exchange_shop
        rather than from here. The flight itinerary
        (`items[].confirmation.details.flight.legs`) is the one booked and
        ticketed. It is not refreshed from the airline, and no webhook reports
        an airline's schedule change or cancellation."
    GetBookingResponse:
      type: object
      properties:
        booking:
          $ref: "#/components/schemas/Booking"
      example:
        booking:
          booking_ref: JNK-A0AUR2
          booking_reference: JNK-A0AUR2
          status: completed
          type: flight
          last_name: Doe
          total_paid:
            value: 31840
            currency: USD
            decimal_places: 2
            display: USD 318.40
          created_at: "2026-05-20T09:14:00Z"
          calendar:
            files:
              - method: REQUEST
                filename: jinko-JNK-A0AUR2.ics
                content_type: text/calendar; charset=utf-8; method=REQUEST
                content: BEGIN:VCALENDAR\r\nVERSION:2.0\r\n…\r\nEND:VCALENDAR\r\n
    GetBookingRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        intent:
          $ref: "#/components/schemas/IntentInput"
      required:
        - booking_ref
    SupportLevel:
      type: string
      enum:
        - AUTO
        - MANUAL_REQUIRED
        - UNSUPPORTED
      description: How this action can be carried out. `AUTO` — the platform completes
        it end to end through the API. `MANUAL_REQUIRED` — it is possible, but a
        Jinko agent has to act; call the API to raise it and expect a delay
        rather than an immediate result. `UNSUPPORTED` — the provider or fare
        does not allow it at all; nothing you send will change that. Do not
        treat MANUAL_REQUIRED as a failure, and do not retry UNSUPPORTED. On the
        refund check `manual_reason` says why it is not `AUTO`, on the exchange
        shop `reason`.
    RefundCheckResponse:
      type: object
      properties:
        seat_refunds:
          type: array
          items:
            $ref: "#/components/schemas/SeatRefund"
          description: Separate refunds for carrier-settled paid seats. A paid seat is
            refunded once the airline refunds Jinko; these amounts are not part
            of the quoted fare refund.
        is_refundable:
          type: boolean
          description: "Whether the fare that was sold is refundable under its fare rules:
            the same answer the price check gave. A non-refundable ticket can
            still be given back in full while it is inside its void window; read
            `is_voidable` for that."
          example: true
        is_voidable:
          type: boolean
          description: True when committing would VOID the ticket outright — the document
            is still inside its void window, so the original charge is reversed
            in full instead of a fare-rule refund being computed. This check
            returns eligibility only; use flight_refund_preview for
            customer-facing amounts. Time-sensitive — read it from a live check,
            never from stored booking data.
          example: false
        is_automatable:
          type: boolean
          example: true
        support_level:
          $ref: "#/components/schemas/SupportLevel"
        manual_reason:
          type: string
          description: Why the refund is not automatic or not available, in words the
            customer can be shown; never the supplier’s wording. Present
            whenever `support_level` is not `AUTO`. With `UNSUPPORTED` it is the
            sentence a `flight_refund_preview` refusal (409 `not_cancellable`)
            carries for the same booking. With `MANUAL_REQUIRED`, where the
            reason would be the supplier’s own words, it reads “This request
            needs manual handling by Jinko support.”
          example: fare rules require agent review
        reason_code:
          type: string
          description: "Why the refund is not automatic or not available, as a code to
            route on: `NON_REFUNDABLE_FARE`, `EXCHANGED_TICKET`,
            `DOCUMENT_RETIRED`, `CARRIER_NOT_AUTHORIZED`, `NOT_CANCELLABLE` (a
            refusal the supplier gave no code for). When `support_level` is
            `UNSUPPORTED`, it is always present and is the same code a
            `flight_refund_preview` refusal (409 `not_cancellable`) carries for
            this booking."
          example: NON_REFUNDABLE_FARE
        expires_at:
          type: string
          example: "2026-06-02T00:00:00Z"
        warnings:
          type: array
          items:
            type: string
          description: Notes about the booking and its documents, each said once, in words
            the customer can be shown. A note the supplier sends as free text
            without a code is left out.
    FlightServicingConflictCode:
      type: string
      enum:
        - quote_drift
        - QUOTE_EXPIRED
        - active_operation_exists
        - not_cancellable
        - funds_unavailable
        - superseded
        - manual_required
        - penalty_exceeds_sell
        - multi_currency_basis
      description: "Which refusal this is. `manual_required` — the quote needs a Jinko
        agent and you did not send `manual_ok: true`; resend the same commit
        with it to hand the operation over. It can also mean the supplier’s
        totals use inconsistent currencies or decimal places, or the
        cancellation’s booking fee cannot be established or the booking has
        already had a completed exchange. These cases require a Jinko operator
        to complete the cancellation; contact Jinko support with the booking
        reference. `quote_drift` — your acknowledged figure differs from the
        still-live quote’s refund. `retry_quote_id` is that same quote’s handle
        and `current.refund` its figure. Show it to the customer, then commit
        again with that handle and figure. `QUOTE_EXPIRED` — the quote stopped
        binding; take a fresh one. `active_operation_exists` — an operation is
        already running on this booking; poll `active_operation` when present
        instead of starting a second. `not_cancellable` — usually the airline
        refuses to refund this ticket as it stands (a non-refundable fare, or
        every document already voided or refunded), with its reason in
        `error.message`. When `reason_code` is `already_cancelled`, Jinko
        already recorded a successful cancellation for this booking; this is not
        a supplier answer. The preview answers it too, so it is not a
        commit-only case. `booking_not_active` means the booking is no longer
        active; `error.message` is the platform’s sentence. `funds_unavailable`
        — the original payment cannot cover the refund yet; `shortfall` is how
        much is missing and `blocking` names the refunds that have to settle
        first. `superseded` — the item this quote named is no longer the live
        one with the airline (an exchange moved it); preview again; there is no
        `retry_quote_id`. The last two arrive only on a commit against a quote
        that already answered `commitable: false`, and repeat that quote’s own
        `not_commitable_reason`: `penalty_exceeds_sell` — the penalty is at
        least what the customer paid, so there is nothing to refund;
        `multi_currency_basis` — the airline prices the refund in a currency the
        customer was not charged in, so no single figure exists and a Jinko
        agent has to settle it. In every case NOTHING was sent to the airline."
    FlightServicingConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          $ref: "#/components/schemas/FlightServicingConflictCode"
        reason_code:
          type: string
          pattern: ^[A-Za-z_]{1,64}$
          description: "Machine-readable reason for the servicing refusal.
            `already_cancelled` means this booking already has a successful
            cancellation recorded by Jinko; it is not a supplier answer.
            `booking_not_active` means get_booking returns a booking whose
            status is failed (for example, after payment), expired_quote,
            pending or exchange_partial_failure. Refund and hotel servicing
            routes refuse it with `code: not_cancellable` and a platform
            sentence in `error.message`, to a caller who may service the
            booking; any other caller gets the same 404 as for an unknown
            booking."
          example: already_cancelled
        retry_quote_id:
          type: string
          description: The quote to commit against when your acknowledged figure differs
            from a still-live quote’s refund (`quote_drift`). This is the same
            `quote_id`, not a new one. Show the customer `current.refund`, then
            commit again with this `quote_id` and that figure. Absent on
            `QUOTE_EXPIRED`, `superseded`, or a hotel `quote_drift` because the
            supplier’s policy moved since the quote. Preview again in those
            cases.
          example: svq_01J8AB4N7GLY3Q0D
        requote:
          type: string
          description: "Deprecated: use `retry_quote_id` instead. Same value."
          example: svq_01J8AB4N7GLY3Q0D
          deprecated: true
        current:
          type: object
          properties:
            refund:
              $ref: "#/components/schemas/Money"
          description: The quote’s refund, on `quote_drift`. When `retry_quote_id` is
            present, show this figure to the customer, then commit again with
            that handle and this figure.
        active_operation:
          type: string
          description: The operation already running on this booking, on
            `active_operation_exists`. Present when the running operation
            belongs to this booking and can be polled with the status route; it
            may be absent otherwise. Poll it with the status route for its
            domain — POST /v1/hotel_cancel_status or POST
            /v1/flight_refund_status.
          example: svc_01J7ZR5Q2KME8V4T
        shortfall:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: How much of the refund could not be reserved, on
                `funds_unavailable`. The refusal is about money still moving on
                the original payment, not about this booking, so this is the
                figure that says how much has to clear before a commit can
                succeed.
        blocking:
          type: array
          items:
            type: string
          description: 'What is holding that money, on `funds_unavailable`: the refunds
            already in flight against the same payment, which have to settle
            before this one can be reserved. Opaque handles — read them as
            identity, do not parse them. This is what to wait on; without it,
            "retry later" has nothing behind it.'
          example:
            - re_3UBIxK2eZvKYlo2C
      required:
        - error
        - code
    RefundCheckRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
      example: &a26
        booking_ref: JNK-A0AUR2
        last_name: Doe
    ServicingState:
      type: string
      enum:
        - in_progress
        - attention_required
        - succeeded
        - failed
      description: "Where the cancellation has got to. `in_progress` — running; keep
        polling. `attention_required` — stalled on something a person at Jinko
        has to resolve (`reason` names it); keep polling, and do not report it
        to the customer as a failure, because the booking may already be
        cancelled at the supplier. `succeeded` and `failed` are terminal: the
        supplier outcome and the money are both settled and nothing further will
        change."
    FlightOperationKind:
      type: string
      enum:
        - cancel
        - void
      description: What the platform would do, or did. `cancel` — refund the ticket
        under the fare rules, less the penalty. `void` — the ticket is inside
        its void window, so it is voided and the original charge is reversed in
        full, penalty-free. The platform decides from the live state of the
        documents; the caller cannot ask for one.
    RefundCommitResponse:
      type: object
      properties:
        refund_status:
          type: string
          enum:
            - PENDING
            - IN_PROGRESS
            - SUCCEEDED
            - FAILED
            - MANUAL_REQUIRED
            - UNCONFIRMED
            - CANCELLED
          description: "The refund's processing status. `PENDING` and `IN_PROGRESS` mean
            it is still running — poll `operation`. `MANUAL_REQUIRED` means a
            Jinko agent has it: raised, parked, NOT failed. `UNCONFIRMED` means
            the airline has not settled its answer yet. `SUCCEEDED`, `FAILED`
            and `CANCELLED` are terminal. `state` beside it reports the same
            operation in the platform vocabulary; either is enough to decide
            whether to keep polling."
          example: IN_PROGRESS
        operation:
          type: string
          description: The refund this call started ("svc_…"). Refunding at the airline
            and returning the money to the customer's card are separate steps,
            so this call answering does not mean both finished — poll the handle
            with POST /v1/flight_refund_status until `state` is terminal.
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        operation_kind:
          $ref: "#/components/schemas/FlightOperationKind"
        refund_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "THE CUSTOMER FIGURE: what goes back to the payment method that
                paid for this ticket — what they paid, less the penalty, or the
                whole charge when the ticket was voided (`operation_kind:
                void`). All amounts are customer-facing only. Absent is not
                zero."
        refund_reference:
          type: string
          example: svc_agqsfzamchoagwznss4z3gwobm5tpxx3r4n5tfrngy
        warnings:
          type: array
          items:
            type: string
    RefundCommitRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
      example: *a26
    RefundStatusResponse:
      type: object
      properties:
        refund_status:
          type: string
          description: Where the refund has got to. Current refunds use `PENDING`,
            `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `MANUAL_REQUIRED`,
            `UNCONFIRMED`, or `CANCELLED`. Older refunds may report other status
            values, which is why this field is not published as a closed list.
            Treat an unrecognised value as "still running" and poll `state`,
            which is one vocabulary for both.
          example: SUCCEEDED
        operation:
          type: string
          description: The refund being reported ("svc_…"), for refunds started on the
            servicing path. POST /v1/flight_refund_status reads the same
            operation and adds where the money itself has got to.
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        refund_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "THE CUSTOMER FIGURE: what goes back to the payment method — the
                settled figure once the refund has settled, the quoted one
                before. Absent is not zero."
        refund_reference:
          type: string
          example: svc_agqsfzamchoagwznss4z3gwobm5tpxx3r4n5tfrngy
        warnings:
          type: array
          items:
            type: string
    RefundStatusRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        refund_reference:
          type: string
      example: *a26
    ExchangeOfferSegment:
      type: object
      properties:
        airline:
          type: string
          description: IATA code of the MARKETING carrier — whose flight number this is.
          example: AA
        operating_carrier:
          type: string
          description: IATA code of the carrier that flies the aircraft. Differs from
            `airline` on a codeshare.
          example: BA
        flight_number:
          type: string
          description: Provider flight number, forwarded unchanged. Depending on the
            upstream provider it may be a bare number such as `460` or a
            composed designator such as `AS460`; the carrier code is also
            carried separately when known.
          example: "6957"
        departure_airport:
          type: string
          example: MIA
        departure_time:
          type: string
          description: Local wall-clock time at the airport, `YYYY-MM-DDTHH:MM:SS` with no
            UTC offset (e.g. `2026-11-24T19:35:00`). Do not read it as UTC.
          example: "2026-11-24T19:35:00"
        arrival_airport:
          type: string
          example: LHR
        arrival_time:
          type: string
          description: Local wall-clock time at the airport, `YYYY-MM-DDTHH:MM:SS` with no
            UTC offset (e.g. `2026-11-24T19:35:00`). Do not read it as UTC.
          example: "2026-11-25T09:05:00"
        duration_minutes:
          type: number
          example: 530
        cabin_name:
          type: string
          description: The cabin of the fare on this segment, as the airline names it.
          example: Economy
        fare_brand_key:
          type: string
          description: The fare brand on this segment, as the supplier keys it. The
            offer-level `fare_brand_code` / `fare_brand_name` are the ones to
            show.
          example: MAINSL
        fare_basis_code:
          type: string
          description: The fare basis code the airline prices this segment with.
          example: OVAIZNB3
        rbd:
          type: string
          description: The booking class (reservation booking designator) on this segment.
          example: O
    ExchangeOfferLeg:
      type: object
      properties:
        stops:
          type: integer
          example: 0
        duration_minutes:
          type: number
          example: 530
        segments:
          type: array
          items:
            $ref: "#/components/schemas/ExchangeOfferSegment"
          description: The flown segments of this journey, in travel order.
    ExchangeOffer:
      type: object
      properties:
        offer_id:
          type: string
          description: The handle POST /v1/exchange_price and /v1/exchange_commit take.
          example: exch_offer_3c1a9f
        description:
          type: string
          example: AA100, 23 Sep, JFK-DFW-SJC
        estimated_payment_outcome:
          type: string
          description: What the money is expected to do — additional payment due, a
            refund, or even. An ESTIMATE from the shop step; POST
            /v1/exchange_price is the binding figure.
          example: additional_payment_due
        estimated_amount:
          $ref: "#/components/schemas/Money"
        non_refundable_amount:
          $ref: "#/components/schemas/Money"
        validating_carrier:
          type: string
          example: AA
        fare_brand_code:
          type: string
          description: The airline’s code for the fare brand this alternative sells. One
            itinerary can come back as several offers — one per brand — on the
            same flight and booking class, differing only in brand, fare basis
            and price; this and `fare_brand_name` are what tell them apart.
            Absent when the airline states no single brand for the offer.
          example: MAINSL
        fare_brand_name:
          type: string
          description: The fare brand’s display name, as the airline states it. Show this
            to the customer rather than `fare_brand_code`. Absent when the
            airline states no single brand.
          example: MAIN SELECT
        legs:
          type: array
          items:
            $ref: "#/components/schemas/ExchangeOfferLeg"
          description: The itinerary this alternative puts the traveller on, one entry per
            journey in travel order. Absent when the supplier returned no
            itinerary for the offer; `description` is then all that is known.
        fare_basis_codes:
          type: array
          items:
            type: string
          description: The fare basis codes of the alternative, in segment order.
          example:
            - OVAIZNB3
        booking_classes:
          type: array
          items:
            type: string
          description: The booking classes of the alternative, in segment order.
          example:
            - O
        cabin:
          type: string
          example: Economy
    ExchangeShopResponse:
      type: object
      properties:
        support_level:
          $ref: "#/components/schemas/SupportLevel"
        reason_code:
          type: string
          description: "Why the exchange is not automatic, as a Jinko code to route on,
            never a supplier’s. Present whenever `support_level` is not `AUTO`,
            absent when it is. Today `NOT_EXCHANGEABLE` with `support_level:
            UNSUPPORTED` — the booking cannot be exchanged online — and
            `MANUAL_REQUIRED` with `support_level: MANUAL_REQUIRED` — a Jinko
            agent has to carry out the exchange."
          example: NOT_EXCHANGEABLE
        reason:
          type: string
          description: "Why the exchange is not automatic, in words the customer can be
            shown. Present whenever `support_level` is not `AUTO`, absent when
            it is. It is a fixed Jinko sentence and never the supplier’s
            wording: “This booking cannot be exchanged online. Contact Jinko
            support.” with `NOT_EXCHANGEABLE`, “This request needs manual
            handling by Jinko support.” with `MANUAL_REQUIRED`."
          example: This booking cannot be exchanged online. Contact Jinko support.
        offers:
          type: array
          items:
            $ref: "#/components/schemas/ExchangeOffer"
        warnings:
          type: array
          items:
            type: string
          description: Notes about the booking and its documents, each said once, in words
            the customer can be shown. A note the supplier sends as free text
            without a code is left out.
    ExchangeLegSelection:
      type: object
      properties:
        origin_location:
          type: object
          properties:
            code:
              type: string
            type:
              type: string
              enum: *a9
          required:
            - code
            - type
        destination_location:
          type: object
          properties:
            code:
              type: string
            type:
              type: string
              enum: *a9
          required:
            - code
            - type
        departure_date:
          type: string
          format: date
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: The new departure date for this booked leg (YYYY-MM-DD).
      required:
        - origin_location
        - destination_location
        - departure_date
    ExchangeShopRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        segments_to_exchange:
          type: array
          items:
            $ref: "#/components/schemas/ExchangeLegSelection"
          minItems: 1
          description: "The legs to change. Each entry is matched to a booked leg by its
            origin and destination and gives the new departure date. Booked legs
            you do not list are kept unchanged: every offer is the whole
            itinerary, with the kept legs as booked. Name each leg by its booked
            airport codes (`type: airport`): the first departure and the last
            arrival airport of that journey, as get_booking lists the leg — not
            a connection airport. A city code cannot be matched and is refused.
            An entry that matches no booked leg is refused with 400
            `INVALID_SEGMENTS_TO_EXCHANGE`; a leg that has already departed with
            400 `LEG_ALREADY_DEPARTED`; a date before today at the departure
            airport with 400 `DEPARTURE_DATE_IN_PAST`; new dates that would put
            the legs out of order with 400 `LEG_DATES_OUT_OF_ORDER`. Each
            refusal lists the booked legs. Some suppliers cannot keep a leg yet;
            for those bookings a request that names only some of the legs is
            refused with 400 `PARTIAL_EXCHANGE_UNSUPPORTED` — name every leg to
            reshop the whole itinerary."
        preferred_departure_date:
          type: string
          description: Legacy. Moves the FIRST leg of the booking to this date and reshops
            every leg, so it cannot change only a later leg (a return) and can
            replace the flights of a leg you meant to keep. Use
            `segments_to_exchange` instead.
      example: *a26
    ExchangeCustomerAmounts:
      type: object
      properties:
        original_fare:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "What the customer paid for the ticket being exchanged: the fare
                charge on the booking, after any earlier exchange and refund,
                excluding paid seats and bags (an exchange does not re-price
                them)."
        new_fare:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "The new ticket's value to the customer, derived so the figures add
                up: `new_fare = original_fare + total_due - total_refund -
                penalty_amount - residual_value`."
        penalty_amount:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: "The airline's change fee, already inside `total_due` (or taken off
                `total_refund`). Absent when there is no airline change fee:
                absent means none, not unknown."
        total_due:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Exactly what the customer is charged for this exchange. Present
                when `payment_outcome` is `ADD_COLLECT` (above 0) or `EVEN` (0).
                Supplier service fees are never part of it.
        total_refund:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: Exactly what goes back to the customer's original payment. Present
                when `payment_outcome` is `REFUND`.
        residual_value:
          allOf:
            - $ref: "#/components/schemas/MoneyValue"
            - description: The part of the original fare the airline keeps as a credit
                document (EMD) in the traveller's name after an exchange to a
                cheaper fare. It is not refunded to the card by this exchange
                and is not part of total_due or total_refund. Present only when
                the airline reported one. The figures add up as `original_fare +
                total_due - total_refund = new_fare + penalty_amount +
                residual_value`.
      required:
        - original_fare
        - new_fare
      description: "Read the exchange here: the customer's own figures, all in the
        booking's charge currency. Absent when the platform cannot state them;
        the legacy fields beside it are then all there is. They add up to the
        cent: `original_fare + total_due - total_refund = new_fare +
        penalty_amount + residual_value`, an absent figure counting as 0.
        `total_due` and `total_refund` are exactly what is charged to or
        refunded on the customer's payment, the same figures as the top-level
        ones; supplier service fees are never part of them. Baggage prices in
        `new_fare_details` are airline information for buying bags; they are not
        part of `total_due`."
    ExchangePriceResponse:
      type: object
      properties:
        payment_outcome:
          type: string
          description: "What the customer's money does: `ADD_COLLECT` — they pay
            `total_due`; `REFUND` — they get `total_refund` back; `EVEN` —
            nothing moves. It is the customer's outcome, which can differ from
            the supplier's. The list may grow: handle a value you do not know."
          example: ADD_COLLECT
        customer_amounts:
          $ref: "#/components/schemas/ExchangeCustomerAmounts"
        fare_difference:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `customer_amounts` instead. The supplier's
                base-fare difference between the new and the original ticket,
                converted to the booking's charge currency at the rate pinned
                when the booking was priced. It does not reconcile with the
                other figures: `new_fare - original_fare` need not equal it, and
                it is not what the customer pays — `total_due` / `total_refund`
                are."
              deprecated: true
        penalty_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `customer_amounts.penalty_amount` instead. The
                change fee as the supplier states it, converted at the booking's
                pinned rate. On some bookings it is the supplier's own booking
                change fee, which Jinko absorbs: it is not part of `total_due`,
                and adding it to a fare difference overstates what the customer
                pays."
              deprecated: true
        original_fare:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `customer_amounts.original_fare` instead. The
                supplier's value of the ticket being exchanged, converted at the
                booking's pinned rate. It is not necessarily what the customer
                paid."
              deprecated: true
        new_fare:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "Deprecated: use `customer_amounts.new_fare` instead. The
                supplier's price of the new fare, converted at the booking's
                pinned rate. The legacy figures do not add up to it."
              deprecated: true
        total_due:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: Exactly what the customer is charged for this exchange, in the
                booking's charge currency. Supplier service fees are never part
                of it.
        total_refund:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: Exactly what goes back to the customer's original payment, in the
                booking's charge currency.
        new_fare_details:
          type: object
          properties:
            fare_brand_name:
              type: string
              example: MAIN CABIN FLEXIBLE
            fare_brand_code:
              type: string
              example: MAINFL
            fare_basis_codes:
              type: array
              items:
                type: string
              description: The new fare’s basis codes, in segment order.
            endorsements:
              type: string
              description: The ticket endorsement text, verbatim — the source of the two
                booleans below.
              example: USD281.86 NONREFUNDABLE/NONREF/FAREDIF/CXL BY FLT TIME OR NOVALUE
            is_refundable:
              type: boolean
              description: Whether the new fare is refundable. Absent when the fare does not
                say.
            is_changeable:
              type: boolean
              description: Whether the new fare can be changed. Absent when the fare does not
                say.
            refund_policy:
              type: string
              description: The refund rule as a display string.
              example: Non-refundable
            change_policy:
              type: string
              description: The change rule as a display string.
              example: Changeable (conditions apply)
            checked_baggage:
              type: object
              properties:
                pieces:
                  type: integer
                  description: Pieces included. Absent when the fare states none or states zero;
                    `description` then says which ("No checked bags included" is
                    a stated zero).
                weight:
                  type: number
                weight_unit:
                  type: string
                  example: KG
                dimensions:
                  type: string
                description:
                  type: string
                  example: 1 bag, 23kg included
              description: The checked baggage the new fare includes. Absent when the fare
                states none.
            carry_on_baggage:
              type: object
              properties:
                pieces:
                  type: integer
                  description: Pieces included. Absent when the fare states none or states zero;
                    `description` then says which ("No checked bags included" is
                    a stated zero).
                weight:
                  type: number
                weight_unit:
                  type: string
                  example: KG
                dimensions:
                  type: string
                description:
                  type: string
                  example: 1 bag, 23kg included
              description: The carry-on baggage the new fare includes. Absent when the fare
                states none.
            extra_baggage_options:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  pieces:
                    type: integer
                  weight:
                    type: number
                  weight_unit:
                    type: string
                  is_included:
                    type: boolean
                  price_per_bag:
                    $ref: "#/components/schemas/Money"
                  total_price:
                    $ref: "#/components/schemas/Money"
                  description:
                    type: string
                  segment_id:
                    type: string
                  journey_id:
                    type: string
            extra_carry_on_options:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  pieces:
                    type: integer
                  weight:
                    type: number
                  weight_unit:
                    type: string
                  is_included:
                    type: boolean
                  price_per_bag:
                    $ref: "#/components/schemas/Money"
                  total_price:
                    $ref: "#/components/schemas/Money"
                  description:
                    type: string
                  segment_id:
                    type: string
                  journey_id:
                    type: string
        fare_change_notice:
          type: object
          properties:
            original_brand:
              type: string
              example: MAIN SELECT
            new_brand:
              type: string
              example: MAIN CABIN
            refundability_changed:
              type: boolean
              description: True only when both fares state whether they are refundable and the
                two differ. An unstated side leaves it false.
            text:
              type: string
              description: The notice to show the customer before they pay.
        quote_id:
          type: string
          description: This price’s quote. Pass it as `quote_id` to exchange_commit when
            committing the same offer after a refused price, to request manual
            handling.
          example: exch_7a1c93f0
        session_reference:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: exch_7a1c93f0
          deprecated: true
        expires_at:
          type: string
          example: "2026-06-01T13:04:56Z"
        warnings:
          type: array
          items:
            type: string
          description: Notes about the booking and its documents, each said once, in words
            the customer can be shown. A note the supplier sends as free text
            without a code is left out.
    ExchangePriceConflictCode:
      type: string
      enum:
        - funds_unavailable
        - multi_currency_basis
        - manual_required
        - not_exchangeable
      description: "Which refusal this is. `not_exchangeable` — the booking cannot be
        exchanged as it stands: no ticket or flight is left to change, or the
        fare does not permit the change; do not retry, and committing the offer
        does not send it to support. Its `error.message` is “This booking cannot
        be exchanged online. Contact Jinko support.” `funds_unavailable` — the
        exchange would refund more than the original payment can still refund.
        `multi_currency_basis` — the exchange cannot be priced in the currency
        the booking was paid in. `manual_required` — the booking’s charge or the
        payment the refund would go to could not be read; the supplier’s price
        components cannot be identified or do not add up to its total; an
        airline change fee is charged outside the exchange total; or the
        supplier’s totals use inconsistent currencies or decimal places.
        `error.message` states the case in figures where there are any. In every
        case nothing was exchanged or charged. Jinko support can complete
        `funds_unavailable`, `multi_currency_basis` and `manual_required`. To
        request manual handling, commit the same offer: the request then goes to
        Jinko support. This applies to those three codes only; committing a
        `not_exchangeable` offer is refused again with the same code."
    ExchangePriceConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          $ref: "#/components/schemas/ExchangePriceConflictCode"
      required:
        - error
        - code
    ExchangePriceRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        offer_id:
          type: string
          minLength: 1
      required:
        - offer_id
      example:
        booking_ref: JNK-A0AUR2
        last_name: Doe
        offer_id: exch_offer_3c1a9f
    ExchangeCommitResponse:
      type: object
      properties:
        airline_locator:
          type: string
          description: "Deprecated: read the item’s `supplier_references` on POST
            /v1/get_booking, which carries each airline’s record locator with
            the airline that issued it. Airline record locator for the current
            itinerary."
          example: ABC123
          deprecated: true
        booking_ref:
          type: string
          example: JNK-A0AUR2
        booking_reference:
          type: string
          description: "Deprecated: use `booking_ref` instead. Same value."
          example: JNK-A0AUR2
          deprecated: true
        new_ticket_numbers:
          type: array
          items:
            type: string
          example:
            - "0012345678901"
        status:
          type: string
          enum:
            - confirmed
            - pending
            - partial_failure
            - failed
          description: "A commit answers `pending`: the exchange is carried out after this
            call, whatever the payment outcome. Follow it with exchange_status
            until it reads `confirmed`, `partial_failure` or `failed`."
          example: pending
        payment_outcome:
          type: string
          enum:
            - EVEN
            - ADD_COLLECT
            - REFUND
          description: "`ADD_COLLECT` — the customer pays the difference first: send them
            to `checkout_url`; the exchange runs only after that payment
            authorizes. `EVEN` — nothing to pay. `REFUND` — the difference goes
            back to the original payment method once the exchange completes."
          example: ADD_COLLECT
        checkout_url:
          type: string
          description: "Present when `payment_outcome` is `ADD_COLLECT`: the page where
            the customer pays the difference. Nothing is exchanged until that
            payment authorizes. exchange_status returns the same page while the
            exchange waits for it."
          example: https://app.gojinko.com/checkout?t=eyJyIjoiY2FydCIs…
        stripe_checkout_session_url:
          type: string
          description: "Deprecated: use `checkout_url` instead. The same payment page,
            under a provider’s name."
          deprecated: true
        warnings:
          type: array
          items:
            type: string
          description: Notes about the booking and its documents, each said once, in words
            the customer can be shown. A note the supplier sends as free text
            without a code is left out.
    ExchangeCommitConflictCode:
      type: string
      enum:
        - funds_unavailable
        - multi_currency_basis
        - manual_required
        - exchange_in_progress
        - not_exchangeable
      description: "Which refusal this is. `funds_unavailable`,
        `multi_currency_basis`, `manual_required` — as on exchange_price; the
        request has gone to Jinko support (`manual_handling`).
        `exchange_in_progress` — this booking already has an exchange waiting
        for the customer’s payment or running: nothing new was started;
        exchange_status reports its progress and, while it waits for payment,
        its `checkout_url`. `not_exchangeable` — as on exchange_price: the
        booking cannot be exchanged as it stands, so nothing was started and
        nothing goes to Jinko support; do not retry."
    ExchangeCommitConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          $ref: "#/components/schemas/ExchangeCommitConflictCode"
        manual_handling:
          type: object
          properties:
            status:
              type: string
              enum:
                - pending
              description: "`pending` — the request is with Jinko support, who will complete
                the exchange and refund the customer; nothing else to do. Follow
                it on `get_booking` at `items[].servicing.exchange`."
              example: pending
          required:
            - status
          description: Present on the three refusals that send the request to Jinko support.
      required:
        - error
        - code
    ExchangeCommitRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        offer_id:
          type: string
          minLength: 1
        quote_id:
          type: string
          description: The `quote_id` exchange_price returned. Not required. Optional
            after a refused exchange price, when committing the same offer to
            request manual handling.
      required:
        - offer_id
      example:
        booking_ref: JNK-A0AUR2
        last_name: Doe
        offer_id: exch_offer_3c1a9f
        quote_id: exch_7a1c93f0
    ExchangeStatusResponse:
      type: object
      properties:
        airline_locator:
          type: string
          description: "Deprecated: read the item’s `supplier_references` on POST
            /v1/get_booking, which carries each airline’s record locator with
            the airline that issued it. Airline record locator for the current
            itinerary."
          example: ABC123
          deprecated: true
        booking_ref:
          type: string
          example: JNK-A0AUR2
        booking_reference:
          type: string
          description: "Deprecated: use `booking_ref` instead. Same value."
          example: JNK-A0AUR2
          deprecated: true
        status:
          type: string
          enum:
            - confirmed
            - pending
            - partial_failure
            - failed
          description: "`pending` until the exchange is carried out — including while it
            waits for the customer’s payment, and while a Jinko agent has it
            (`manual_handling`)."
          example: confirmed
        new_ticket_numbers:
          type: array
          items:
            type: string
          example:
            - "0012345678901"
        confirmed_payment_outcome:
          type: string
          example: paid
        checkout_url:
          type: string
          description: "Present while the exchange waits for the customer to pay the
            difference: the same page exchange_commit returned. The exchange
            runs once that payment authorizes."
          example: https://app.gojinko.com/checkout?t=eyJyIjoiY2FydCIs…
        manual_handling:
          type: object
          properties:
            status:
              type: string
              enum:
                - pending
              description: "`pending` — a Jinko agent has the exchange and will complete or
                fail it."
              example: pending
          required:
            - status
          description: "Present while the exchange is with a Jinko agent: it could not be
            completed automatically. `status` stays `PENDING` and polling does
            not move it; the agent does. Absent once the exchange is carried out
            or failed."
        warnings:
          type: array
          items:
            type: string
          description: Notes about the booking and its documents, each said once, in words
            the customer can be shown. A note the supplier sends as free text
            without a code is left out.
    ExchangeStatusRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        order_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref, never
            beside it, and needs a credential that owns the booking. Accepted
            until 2027-04-30; a request that sends it is answered with
            `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
      example: *a26
    HotelCancelResponse:
      type: object
      properties:
        booking_ref:
          type: string
          example: JNK-A0AUR2
        booking_reference:
          type: string
          description: "Deprecated: use `booking_ref` instead. Same value."
          example: JNK-A0AUR2
          deprecated: true
        confirmation_number:
          type: string
          description: "Deprecated: read the item’s `supplier_references` on POST
            /v1/get_booking, which names who issued each reference.
            Customer-facing hotel confirmation number, when supplied by the
            hotel."
          deprecated: true
        status:
          type: string
          example: cancelled
        operation:
          type: string
          description: The cancellation this call started ("svc_…"). Cancelling the
            booking at the supplier and returning the money are separate steps,
            so this call answering does not mean both finished — poll the handle
            with POST /v1/hotel_cancel_status until `state` is terminal.
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        refund_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: "THE CUSTOMER FIGURE: what goes back to the payment method that
                paid for this booking — what the customer paid for it, less
                `penalty_amount`. Up to contract version 0.3.0 this field
                carried the SUPPLIER's net refund instead, which on a booking
                sold at a margin is a smaller number. Only customer-facing
                amounts are published. Absent when no refund was scheduled —
                absent is not zero."
        customer_refund_amount:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: Deprecated alias of `refund_amount`, carrying the same value. It
                existed because `refund_amount` used to be the supplier figure;
                now that `refund_amount` IS the customer figure the alias is
                redundant. Read `refund_amount` — this field is removed in the
                next contract version.
              deprecated: true
        penalty_amount:
          anyOf:
            - $ref: "#/components/schemas/Money"
            - type: object
              properties:
                fee_known:
                  type: boolean
                  enum:
                    - false
              required:
                - fee_known
          description: "The cancellation penalty withheld from the customer, on the same
            basis as `refund_amount`: what they paid, less this, is what they
            get back. When unknown, the amount is omitted; a fee_known: false
            marker may remain."
        cancelled_at:
          type: string
          example: "2026-06-01T12:34:56Z"
        idempotent:
          type: boolean
          example: false
    HotelCancelRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_booking_id:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        provider:
          type: string
          description: "Deprecated: omit it. The platform uses the supplier recorded with
            the booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
    ServicingSupportLevel:
      type: string
      enum:
        - AUTO
        - MANUAL_REQUIRED
      description: 'How this cancellation would be carried out. `AUTO` — the platform
        completes it end to end. `MANUAL_REQUIRED` — it is possible, but a Jinko
        agent has to act; expect a delay rather than an immediate result, and do
        not treat it as a failure; `manual_reason` says why. There is no
        "unsupported" level: a supplier that cannot be cancelled through the API
        arrives as `commitable: false` with `not_commitable_reason:
        provider_unsupported`, and a booking the supplier will not cancel as it
        stands arrives as a 409 `not_cancellable` — from the preview as well as
        the commit — with `error.message` “This booking cannot be cancelled
        online. Contact Jinko support.”'
    HotelCancelPreviewResponse:
      type: object
      properties:
        quote_id:
          type: string
          description: This quote. Pass it as `quote_id` to POST /v1/hotel_cancel_commit —
            it binds the commit to the figures below. Opaque; the format may
            evolve.
          example: svq_01J7ZR3M8FKX2P9C
        quote:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: svq_01J7ZR3M8FKX2P9C
          deprecated: true
        state:
          type: string
          description: Lifecycle of the QUOTE, not of a cancellation — nothing has been
            cancelled by this call. `completed` means the figures are final
            until `expires_at`.
          example: completed
        commitable:
          type: boolean
          description: Whether a commit against this quote would be accepted right now.
            When false, `not_commitable_reason` says why and committing is
            pointless.
          example: true
        support_level:
          $ref: "#/components/schemas/ServicingSupportLevel"
        manual_reason:
          type: string
          description: "Why a person has to act, in words the customer can be shown.
            Present with `support_level: MANUAL_REQUIRED`. Where the reason
            would be the supplier’s own words, it reads “This request needs
            manual handling by Jinko support.” `not_commitable_reason` is the
            code to branch on; this is the sentence to show."
          example: the supplier's cancellation policy names no fee in force for this
            booking, so the fee could not be established
        expires_at:
          type: string
          description: When this quote stops binding. Committing after it answers 409
            `QUOTE_EXPIRED`; take a fresh quote and show the customer the new
            figure before committing again.
          example: "2026-09-03T12:15:00Z"
        booked_item_id:
          type: string
          description: The booked item this quote would cancel — the `booked_item_id`
            get_booking returns. A booking holding several items is quoted and
            cancelled one item at a time.
          example: itm_7f2c9a4e8b1d
        item:
          type: string
          description: "Deprecated: use `booked_item_id` instead. Same value."
          example: itm_7f2c9a4e8b1d
          deprecated: true
        refund:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The refund figure. Absent when the figure is not known.
            basis:
              type: string
              description: How the figure was computed. `sell_minus_penalty` — what the
                customer paid for this item, less the penalty. `original_charge`
                — the entire charge is reversed, penalty-free (a void). The
                platform chooses; the caller cannot ask for one.
              example: sell_minus_penalty
          description: "THE CUSTOMER FIGURE: what would go back to the payment method, on
            the basis named in `basis`. Show this one. Absent is not zero."
        penalty:
          anyOf:
            - type: object
              properties:
                amount:
                  type: number
                  description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                    some endpoints (the two never appear together); its scale
                    depends on decimal_places. When this object carries
                    decimal_places, amount is an INTEGER in minor units — divide
                    by 10 ** decimal_places (e.g. select_ancillaries
                    total_with_ancillaries). When there is no decimal_places
                    field, amount is a decimal in MAJOR units, safe to display
                    as-is (e.g. trip and checkout totals)."
                  deprecated: true
                value:
                  type: integer
                  description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                    units, always paired with decimal_places — divide by 10 **
                    decimal_places to display. Example: value 15977 with
                    decimal_places 2 is 159.77 USD. Rendering this field
                    directly shows prices 100x too high for 2-decimal
                    currencies."
                  example: 41250
                  deprecated: true
                currency:
                  type: string
                  description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
                  example: USD
                  deprecated: true
                decimal_places:
                  type: integer
                  description: "Deprecated: use `amount_money` instead. Scale of the integer
                    value/amount: display = integer / 10 ** decimal_places.
                    Always sent alongside minor-unit amounts. Usually the ISO
                    4217 digits of the currency (2 for USD/EUR/GBP, 0 for
                    JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices
                    can carry a different scale — ALWAYS use the decimal_places
                    sent with the amount, never a hardcoded 2. Only if the field
                    is genuinely absent on a value-shaped object, fall back to
                    the ISO digits for the currency."
                  example: 2
                  deprecated: true
                display:
                  type: string
                  description: 'Deprecated: use `amount_money` instead. The same figure as a
                    string ready to show: the ISO 4217 code, a space, then the
                    amount, e.g. "USD 159.77". With decimal_places it is written
                    at exactly that scale (value 1561500, JPY, decimal_places 2
                    is "JPY 15615.00"); without, at the ISO digits of the
                    currency. Show this; compute with the number. Absent when
                    the figure is not money (a cancellation step expressed as a
                    percent or a number of nights) or could not be read
                    unambiguously.'
                  example: USD 412.50
                  deprecated: true
                amount_money:
                  allOf:
                    - $ref: "#/components/schemas/MoneyValue"
                    - description: The penalty figure. Present only when `fee_known` is true; absent
                        when the fee is unknown, which is not zero.
                fee_known:
                  type: boolean
                  description: false means the penalty could not be established — UNKNOWN, not
                    zero. Render it as "we will confirm the fee", never as free
                    cancellation, and expect the final figure on the operation
                    status.
                  example: true
            - type: object
              properties:
                fee_known:
                  type: boolean
                  enum:
                    - false
              required:
                - fee_known
          description: "What the customer would forfeit. When unknown, the amount is
            omitted; a fee_known: false marker may remain. Absent is not zero.
            Read `fee_known` before showing it."
        policy:
          type: object
          properties:
            free_cancel_until:
              type: string
              nullable: true
              description: The last instant at which cancelling costs nothing. `null` means
                there is no free window — either the booking never had one or it
                has passed.
              example: "2026-09-01T00:00:00Z"
            is_refundable_now:
              type: boolean
              example: true
            tiers:
              type: array
              items:
                type: object
                properties:
                  from:
                    type: string
                    description: When this step starts applying.
                    example: "2026-09-01T00:00:00Z"
                  amount:
                    $ref: "#/components/schemas/Money"
                  fraction:
                    type: number
                    description: The share of the paid price withheld from `from` onwards, when the
                      supplier states the step as a proportion rather than a
                      sum. A step carries `amount` or `fraction`, not both.
                    example: 0.5
              description: "The supplier's policy steps in time order. Informational: the
                figure that binds is `penalty`, computed for right now."
          description: The supplier's cancellation policy as it stands, for explaining the
            figures to the customer.
        not_commitable_reason:
          type: string
          description: 'Why `commitable` is false. Today: `penalty_exceeds_sell` (the
            penalty is at least what the customer paid), `multi_currency_basis`
            (the supplier prices the fee in a currency the customer was not
            charged in, so no single refund figure exists). A fee the supplier’s
            policy does not establish (`penalty.fee_known: false`) is
            `support_level: MANUAL_REQUIRED` with no reason code — read
            `manual_reason`. Two refusals are never values here: a booking the
            supplier will not cancel as it stands is 409 `not_cancellable` from
            this preview itself, and a supplier with no cancellation route is
            422 `provider_unsupported`. The contract reserves further values
            (`provider_unsupported`, `funds_unavailable`,
            `insufficient_time_to_converge`) and new reasons may be added, so
            treat an unrecognised value as "not right now".'
          example: penalty_exceeds_sell
    ServicingConflictCode:
      type: string
      enum:
        - quote_drift
        - QUOTE_EXPIRED
        - active_operation_exists
        - not_cancellable
        - funds_unavailable
        - superseded
      description: Which refusal this is. `quote_drift` — your acknowledged figure
        differs from the still-live quote’s refund. `retry_quote_id` is that
        same quote’s handle and `current.refund` its figure. Show it to the
        customer, then commit again with that handle and figure. If the
        supplier’s policy moved since the quote, `quote_drift` has no
        `retry_quote_id`; preview again. `QUOTE_EXPIRED` — the quote stopped
        binding; take a fresh one. `active_operation_exists` — one cancellation
        is already running on this booking; poll `active_operation` when present
        instead of starting a second. `not_cancellable` — usually the supplier
        refuses to cancel this booking as it stands (already cancelled, never
        confirmed), with its reason in `error.message`. When `reason_code` is
        `already_cancelled`, Jinko already recorded a successful cancellation
        for this booking; this is not a supplier answer. The preview answers it
        too, so it is not a commit-only case. `booking_not_active` means the
        booking is no longer active; `error.message` is the platform’s sentence.
        `funds_unavailable` — the original payment cannot cover the refund yet;
        `shortfall` is how much is missing and `blocking` names the refunds that
        have to settle first. `superseded` — the item this quote named is no
        longer the live one with the supplier (an exchange moved it); preview
        again; there is no `retry_quote_id`. In every case NOTHING was
        cancelled.
    ServicingConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          $ref: "#/components/schemas/ServicingConflictCode"
        reason_code:
          type: string
          pattern: ^[A-Za-z_]{1,64}$
          description: "Machine-readable reason for the servicing refusal.
            `already_cancelled` means this booking already has a successful
            cancellation recorded by Jinko; it is not a supplier answer.
            `booking_not_active` means get_booking returns a booking whose
            status is failed (for example, after payment), expired_quote,
            pending or exchange_partial_failure. Refund and hotel servicing
            routes refuse it with `code: not_cancellable` and a platform
            sentence in `error.message`, to a caller who may service the
            booking; any other caller gets the same 404 as for an unknown
            booking."
          example: already_cancelled
        retry_quote_id:
          type: string
          description: The quote to commit against when your acknowledged figure differs
            from a still-live quote’s refund (`quote_drift`). This is the same
            `quote_id`, not a new one. Show the customer `current.refund`, then
            commit again with this `quote_id` and that figure. Absent on
            `QUOTE_EXPIRED`, `superseded`, or a hotel `quote_drift` because the
            supplier’s policy moved since the quote. Preview again in those
            cases.
          example: svq_01J8AB4N7GLY3Q0D
        requote:
          type: string
          description: "Deprecated: use `retry_quote_id` instead. Same value."
          example: svq_01J8AB4N7GLY3Q0D
          deprecated: true
        current:
          type: object
          properties:
            refund:
              $ref: "#/components/schemas/Money"
          description: The quote’s refund, on `quote_drift`. When `retry_quote_id` is
            present, show this figure to the customer, then commit again with
            that handle and this figure.
        active_operation:
          type: string
          description: The operation already running on this booking, on
            `active_operation_exists`. Present when the running operation
            belongs to this booking and can be polled with the status route; it
            may be absent otherwise. Poll it with the status route for its
            domain — POST /v1/hotel_cancel_status or POST
            /v1/flight_refund_status.
          example: svc_01J7ZR5Q2KME8V4T
        shortfall:
          allOf:
            - $ref: "#/components/schemas/Money"
            - description: How much of the refund could not be reserved, on
                `funds_unavailable`. The refusal is about money still moving on
                the original payment, not about this booking, so this is the
                figure that says how much has to clear before a commit can
                succeed.
        blocking:
          type: array
          items:
            type: string
          description: 'What is holding that money, on `funds_unavailable`: the refunds
            already in flight against the same payment, which have to settle
            before this one can be reserved. Opaque handles — read them as
            identity, do not parse them. This is what to wait on; without it,
            "retry later" has nothing behind it.'
          example:
            - re_3UBIxK2eZvKYlo2C
      required:
        - error
        - code
    HotelCancelPreviewRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
      example:
        booking_ref: JNK-H1ZK90
        last_name: Doe
    HotelCancelCommitResponse:
      type: object
      properties:
        operation:
          type: string
          description: The cancellation this call started ("svc_…"). Poll it with POST
            /v1/hotel_cancel_status; it is the only handle that reports how the
            supplier call and the refund ended.
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
    HotelCancelCommitRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        quote_id:
          type: string
          description: The `quote_id` from a preceding POST /v1/hotel_cancel_preview.
            Binds this commit to the figures that quote reported.
          example: svq_01J7ZR3M8FKX2P9C
        acknowledged:
          type: object
          properties:
            value:
              type: integer
              description: "Integer amount in MINOR units, always paired with decimal_places —
                divide by 10 ** decimal_places to display. Example: value 15977
                with decimal_places 2 is 159.77 USD. Rendering this field
                directly shows prices 100x too high for 2-decimal currencies."
              example: 25000
            currency:
              type: string
              minLength: 1
              description: ISO 4217 currency code.
              example: USD
            decimal_places:
              type: integer
              description: "Scale of the integer value/amount: display = integer / 10 **
                decimal_places. Always sent alongside minor-unit amounts.
                Usually the ISO 4217 digits of the currency (2 for USD/EUR/GBP,
                0 for JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices
                can carry a different scale — ALWAYS use the decimal_places sent
                with the amount, never a hardcoded 2. Only if the field is
                genuinely absent on a value-shaped object, fall back to the ISO
                digits for the currency."
              example: 2
          required:
            - value
            - currency
            - decimal_places
          description: "The refund the customer was shown — copy the preview's
            `refund.amount_money` across. Copying the whole `refund` object, as
            older integrations do, is still accepted. All three of `value`
            (minor units), `currency` and `decimal_places` are REQUIRED: the
            platform compares this against the refund as it stands, and a figure
            whose scale is unstated cannot be compared. `amount` is not accepted
            in its place. Any other key, such as `display` or `basis`, is
            ignored. A mismatch against a still-live quote’s refund is answered
            409 `quote_drift`. `retry_quote_id` is that same quote’s handle and
            `current.refund` its figure. Show it to the customer, then commit
            again with that handle and figure. Nothing is cancelled."
      required:
        - quote_id
        - acknowledged
      example:
        booking_ref: JNK-H1ZK90
        last_name: Doe
        quote_id: svq_01J7ZR3M8FKX2P9C
        acknowledged:
          value: 25000
          currency: USD
          decimal_places: 2
    HotelCancelStatusResponse:
      type: object
      properties:
        operation:
          type: string
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        reason:
          type: string
          description: "With `state: attention_required`, why the operation is stalled:
            the value names what Jinko has to resolve, and needs nothing from
            the caller. With `state: failed`, why it ended: `provider_refused`
            (the supplier refused before changing anything),
            `provider_did_not_apply` (the supplier’s record shows it was not
            applied), `not_sent` (it ended before anything was sent to the
            supplier), `QUOTE_EXPIRED` (the quote it was committed on no longer
            stood), `superseded` or `not_cancellable`. Absent on a failed
            operation that recorded none."
          example: settlement_review
        message:
          type: string
          description: "A sentence about why a failed operation ended, where there is one:
            what the supplier’s refusal means, or that its price changed after
            the quote. Present only with `state: failed`; it never states the
            supplier’s figures."
          example: the fare rules do not allow a refund of this ticket
        park_deadline:
          type: string
          description: 'When a parked operation stops waiting for Jinko and is settled or
            failed. Present with `state: attention_required`; it is how long
            "keep polling" lasts.'
          example: "2026-09-10T12:15:00Z"
        next_run_at:
          type: string
          description: When the platform next drives this operation by itself.
            Informational — polling sooner does not make it run sooner.
          example: "2026-09-03T12:20:00Z"
        provider:
          type: object
          properties:
            state:
              type: string
              description: "The supplier's own view of the booking: `confirmed` (still
                standing), `cancelled`, or `pending` (the supplier has not
                settled it yet)."
              example: cancelled
            references:
              type: object
              properties:
                cancellation_reference:
                  type: string
                  description: The reference the supplier issued for the cancellation or refund
                    itself, for example the ticket number a void settles or the
                    supplier’s refund id. It is never the supplier’s identifier
                    for the booking, and is absent when the supplier issued
                    none.
                  example: cxl_2f90a1c3
          description: The supplier's record. It can say `cancelled` while the money is
            still moving — that is the normal middle of a cancellation, not a
            discrepancy.
        money:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The figure being moved.
            direction:
              type: string
              description: Which way the money moves. `refund` on a cancellation.
              example: refund
            vehicle_state:
              type: string
              description: "How far the money itself has got, independently of the supplier:
                `reserved` (earmarked, nothing sent), `refund_pending`
                (submitted to the payment provider), `payout_initiated` and
                `payout_settled` (paid out to a third party), `paid` (it has
                reached the customer), `released` (earmark dropped, nothing
                owed), `refund_review` (a person at Jinko has to release it).
                Only `paid` and `payout_settled` mean the customer has the
                money."
              example: paid
            stripe_reference:
              type: string
              description: Deprecated. An internal payment reference.
              example: re_3UBIxK2eZvKYlo2C
              deprecated: true
          description: The refund and where it has got to. Read `vehicle_state` before
            telling a customer they have been refunded.
    HotelCancelStatusRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        operation:
          type: string
          description: The "svc_…" handle from a commit, or from POST /v1/hotel_cancel.
          example: svc_01J7ZR5Q2KME8V4T
      required:
        - operation
      example:
        booking_ref: JNK-H1ZK90
        last_name: Doe
        operation: svc_01J7ZR5Q2KME8V4T
    FlightServicingSupportLevel:
      type: string
      enum:
        - AUTO
        - AUTO_VOID
        - MANUAL_REQUIRED
      description: "How this refund would be carried out. `AUTO` — the platform
        refunds the ticket end to end under the fare rules. `AUTO_VOID` — the
        ticket is still inside the airline's void window, so the platform voids
        it and the ENTIRE charge is reversed, penalty-free; there is no supplier
        figure to report on a void. `MANUAL_REQUIRED` — it is possible, but a
        Jinko agent has to act (`manual_reason` says why): the commit is refused
        unless you send `manual_ok: true`, which hands it to that agent. Do not
        treat MANUAL_REQUIRED as a failure. Time-sensitive: a void window
        closes, so read the level from a live preview."
    FlightDocument:
      type: object
      properties:
        number:
          type: string
          description: The 13-digit ticket or EMD number.
          example: "0012345678901"
        type:
          type: string
          enum:
            - TKT
            - EMD
          description: What the document is. `TKT` — the flight ticket itself. `EMD` — an
            electronic miscellaneous document, which is how an ancillary (a bag,
            a seat) is issued.
        state:
          type: string
          enum:
            - ACTIVE
            - REFUNDED
            - VOIDED
            - INACTIVE
            - PENDING
            - UNKNOWN
          description: "Where the document itself has got to. Every document on a preview
            is `ACTIVE` — that is what makes the quote possible. On a status
            read the values are the outcome per document: `REFUNDED`, `VOIDED`,
            `INACTIVE` (the airline dropped it), `PENDING` (the airline has not
            settled it) or `UNKNOWN` (not yet observed)."
          example: ACTIVE
        recoverable:
          type: boolean
          description: "Whether this document’s value can be recovered through this path.
            `false` on every EMD: the platform has no EMD refund or void
            operation, so an ancillary issued as one is not returned by this
            operation and a person has to recover it."
          example: false
    FlightRefundPreviewResponse:
      type: object
      properties:
        seat_refunds:
          type: array
          items:
            $ref: "#/components/schemas/SeatRefund"
          description: Separate refunds for carrier-settled paid seats. A paid seat is
            refunded once the airline refunds Jinko; these amounts are not part
            of the quoted fare refund.
        quote_id:
          type: string
          description: This quote. Pass it as `quote_id` to POST /v1/flight_refund_commit
            — it binds the commit to the figures below. Opaque; the format may
            evolve.
          example: svq_01J7ZR3M8FKX2P9C
        quote:
          type: string
          description: "Deprecated: use `quote_id` instead. Same value."
          example: svq_01J7ZR3M8FKX2P9C
          deprecated: true
        state:
          type: string
          description: Lifecycle of the QUOTE, not of a refund — nothing has been refunded
            or voided by this call. `completed` means the figures are final
            until `expires_at`.
          example: completed
        commitable:
          type: boolean
          description: "Whether a commit against this quote would be accepted as it
            stands. A MANUAL_REQUIRED quote is never commitable and is still
            SUBMITTABLE: send the commit with `manual_ok: true` to hand it to a
            Jinko agent. Otherwise, when false, `not_commitable_reason` says why
            and committing is pointless."
          example: true
        support_level:
          $ref: "#/components/schemas/FlightServicingSupportLevel"
        manual_reason:
          type: string
          description: "Why a person has to act, in words the customer can be shown.
            Present with `support_level: MANUAL_REQUIRED`. Where the reason
            would be the supplier’s own words, it reads “This request needs
            manual handling by Jinko support.”"
          example: fare rules require agent review
        operation_kind:
          allOf:
            - $ref: "#/components/schemas/FlightOperationKind"
            - description: What this quote would do — refund the ticket under the fare rules
                (`cancel`) or void it (`void`). On a void the whole charge comes
                back and the penalty is zero. The status read reports the
                operation that actually ran under this same name, so the two
                compare directly. The handle that binds this quote is `quote`;
                `operation` is the "svc_…" handle the COMMIT answers, and it
                never appears on a quote.
        settlement_basis:
          type: string
          description: How the refund is settled. `sell_minus_penalty` — what the customer
            paid for this ticket, less the penalty (a cancellation).
            `original_charge` — the whole charge is reversed, penalty-free (a
            void). It follows `operation_kind`, which the platform derives; the
            caller cannot ask for one.
          example: sell_minus_penalty
        expires_at:
          type: string
          description: When this quote stops binding. Committing after it answers 409
            `QUOTE_EXPIRED`; take a fresh quote and show the customer the new
            figure before committing again.
          example: "2026-09-03T12:15:00Z"
        booked_item_id:
          type: string
          description: The booked item this quote covers — the `booked_item_id`
            get_booking returns. A booking holding several items is quoted and
            refunded one item at a time; within an item, every ticket issued for
            it is covered together.
          example: itm_7f2c9a4e8b1d
        item:
          type: string
          description: "Deprecated: use `booked_item_id` instead. Same value."
          example: itm_7f2c9a4e8b1d
          deprecated: true
        refund:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The refund figure. Absent when the figure is not known.
            basis:
              type: string
              description: How the figure was computed. `sell_minus_penalty` — what the
                customer paid for this item, less the penalty. `original_charge`
                — the entire charge is reversed, penalty-free (a void). The
                platform chooses; the caller cannot ask for one.
              example: sell_minus_penalty
          description: "THE CUSTOMER FIGURE: what would go back to the payment method, on
            the basis named in `basis` — what they paid less the penalty, or the
            entire charge on a void. Show this one. Absent is not zero: a quote
            whose penalty is unknown carries no refund figure at all."
        penalty:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The penalty figure. Present only when `fee_known` is true; absent
                    when the fee is unknown, which is not zero.
            fee_known:
              type: boolean
              description: false means the penalty could not be established — UNKNOWN, not
                zero. Render it as "we will confirm the fee", never as free
                cancellation, and expect the final figure on the operation
                status.
              example: true
            breakdown:
              type: object
              properties:
                airline_fee:
                  allOf:
                    - $ref: "#/components/schemas/MoneyValue"
                    - description: The airline’s cancellation fee, taxes on the fee included. This is
                        the figure a fare rule advertises.
                non_refundable_taxes:
                  allOf:
                    - $ref: "#/components/schemas/MoneyValue"
                    - description: The taxes and carrier surcharges the airline does not give back,
                        summed. On a ticket refunded after part of it was used,
                        this includes the taxes of the flights already flown.
                used_fare:
                  allOf:
                    - $ref: "#/components/schemas/MoneyValue"
                    - description: The fare of the flights already flown, on a ticket that is refunded
                        after part of it was used.
              description: "How the supplier itemises the penalty, in the same currency: the
                airline’s cancellation fee, the taxes it does not give back, and
                the fare of flights already flown. Present when the supplier
                states at least one of them; a member the supplier does not
                state is absent, and a stated zero is a zero. The penalty figure
                is what is withheld; the members explain it and may not add up
                to it exactly (each is converted and rounded on its own, and a
                supplier may withhold something it does not itemise)."
          description: What the customer would forfeit, in the currency they were charged.
            Zero on a void. May be omitted when unknown; absent is not zero.
            Read `fee_known` before showing it — false means UNKNOWN, not free.
        documents:
          type: array
          items:
            $ref: "#/components/schemas/FlightDocument"
          description: "Every document this operation covers, each of them active right
            now. Ticket subsets are not offered: the operation takes the whole
            item."
        ancillary_recoverable:
          type: boolean
          description: Whether the ancillaries bought with this ticket come back with it.
            `false` when any document is an EMD — the platform cannot refund or
            void one, so that value has to be recovered by a person, and the
            quote is MANUAL_REQUIRED. Tell the customer before they commit, not
            after.
          example: true
        not_commitable_reason:
          type: string
          description: 'Why `commitable` is false. Today: `manual_required` (a Jinko agent
            has to act — resubmit with `manual_ok: true`; `manual_reason` says
            why), `penalty_exceeds_sell` (the penalty is at least what the
            customer paid), `multi_currency_basis` (the airline prices the
            refund in a currency the customer was not charged in, so no single
            figure exists). Two refusals are never values here: a fare the
            airline will not refund is 409 `not_cancellable` from this preview
            itself, and an airline with no refund route is 422
            `provider_unsupported`. The contract reserves further values
            (`provider_unsupported`, `funds_unavailable`,
            `insufficient_time_to_converge`) and new reasons may be added, so
            treat an unrecognised value as "not right now".'
          example: manual_required
    FlightRefundPreviewRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
      example: *a26
    FlightRefundCommitResponse:
      type: object
      properties:
        operation:
          type: string
          description: The operation this call started ("svc_…"). Poll it with POST
            /v1/flight_refund_status; it is the only handle that reports how the
            airline call and the refund ended.
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        reason:
          type: string
          description: "Why the operation is parked, when `state` is `attention_required`.
            On a commit that is `manual_required`: you sent `manual_ok: true`, a
            Jinko agent now has it, and nothing has been sent to the airline.
            Not a failure — poll the operation."
          example: manual_required
    FlightRefundCommitRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        quote_id:
          type: string
          description: The `quote_id` from a preceding POST /v1/flight_refund_preview.
            Binds this commit to the figures that quote reported.
          example: svq_01J7ZR3M8FKX2P9C
        acknowledged:
          type: object
          properties:
            value:
              type: integer
              description: "Integer amount in MINOR units, always paired with decimal_places —
                divide by 10 ** decimal_places to display. Example: value 15977
                with decimal_places 2 is 159.77 USD. Rendering this field
                directly shows prices 100x too high for 2-decimal currencies."
              example: 25000
            currency:
              type: string
              minLength: 1
              description: ISO 4217 currency code.
              example: USD
            decimal_places:
              type: integer
              description: "Scale of the integer value/amount: display = integer / 10 **
                decimal_places. Always sent alongside minor-unit amounts.
                Usually the ISO 4217 digits of the currency (2 for USD/EUR/GBP,
                0 for JPY/KRW, 3 for BHD/JOD/KWD) but currency-converted prices
                can carry a different scale — ALWAYS use the decimal_places sent
                with the amount, never a hardcoded 2. Only if the field is
                genuinely absent on a value-shaped object, fall back to the ISO
                digits for the currency."
              example: 2
          required:
            - value
            - currency
            - decimal_places
          description: "The refund the customer was shown — copy the preview's
            `refund.amount_money` across. Copying the whole `refund` object, as
            older integrations do, is still accepted. REQUIRED whenever the
            preview carried a `refund`, which is every quote that names a
            figure. It may be omitted in exactly one case: a MANUAL_REQUIRED
            quote that carries no `refund` at all because the penalty is unknown
            (`penalty.fee_known: false`), submitted with `manual_ok: true` —
            there is no figure to acknowledge, and inventing one would have the
            customer agree to a number nobody computed. Omitting it anywhere
            else is refused by the platform, not here. When present, all three
            of `value` (minor units), `currency` and `decimal_places` are
            required: the platform compares this against the refund as it
            stands, and a figure whose scale is unstated cannot be compared.
            `amount` is not accepted in its place. Any other key, such as
            `display` or `basis`, is ignored. A mismatch against a still-live
            quote’s refund is answered 409 `quote_drift`. `retry_quote_id` is
            that same quote’s handle and `current.refund` its figure. Show it to
            the customer, then commit again with that handle and figure. Nothing
            is sent to the airline."
        manual_ok:
          type: boolean
          description: "Send `true` to submit a quote whose `support_level` is
            MANUAL_REQUIRED. The operation is then raised for a Jinko agent and
            answers `state: attention_required` with `reason: manual_required` —
            NOTHING is sent to the airline by this call, and the agent settles
            or fails it. Without the flag such a commit is refused 409
            `manual_required`, so a customer is never put in an agent queue
            unasked. On an AUTO or AUTO_VOID quote the flag changes nothing.
            This is also the one submission that may carry no `acknowledged`
            figure — when the quote itself named none, because the penalty is
            unknown."
          example: false
      required:
        - quote_id
      example:
        booking_ref: JNK-A0AUR2
        last_name: Doe
        quote_id: svq_01J7ZR3M8FKX2P9C
        acknowledged:
          value: 25000
          currency: USD
          decimal_places: 2
    FlightRefundStatusResponse:
      type: object
      properties:
        operation:
          type: string
          example: svc_01J7ZR5Q2KME8V4T
        state:
          $ref: "#/components/schemas/ServicingState"
        reason:
          type: string
          description: "With `state: attention_required`, why the operation is stalled:
            the value names what Jinko has to resolve, and needs nothing from
            the caller. With `state: failed`, why it ended: `provider_refused`
            (the supplier refused before changing anything),
            `provider_did_not_apply` (the supplier’s record shows it was not
            applied), `not_sent` (it ended before anything was sent to the
            supplier), `QUOTE_EXPIRED` (the quote it was committed on no longer
            stood), `superseded` or `not_cancellable`. Absent on a failed
            operation that recorded none."
          example: settlement_review
        message:
          type: string
          description: "A sentence about why a failed operation ended, where there is one:
            what the supplier’s refusal means, or that its price changed after
            the quote. Present only with `state: failed`; it never states the
            supplier’s figures."
          example: the fare rules do not allow a refund of this ticket
        park_deadline:
          type: string
          description: 'When a parked operation stops waiting for Jinko and is settled or
            failed. Present with `state: attention_required`; it is how long
            "keep polling" lasts.'
          example: "2026-09-10T12:15:00Z"
        next_run_at:
          type: string
          description: When the platform next drives this operation by itself.
            Informational — polling sooner does not make it run sooner.
          example: "2026-09-03T12:20:00Z"
        provider:
          type: object
          properties:
            state:
              type: string
              description: "The supplier's own view of the booking: `confirmed` (still
                standing), `cancelled`, or `pending` (the supplier has not
                settled it yet)."
              example: cancelled
            references:
              type: object
              properties:
                cancellation_reference:
                  type: string
                  description: The reference the supplier issued for the cancellation or refund
                    itself, for example the ticket number a void settles or the
                    supplier’s refund id. It is never the supplier’s identifier
                    for the booking, and is absent when the supplier issued
                    none.
                  example: cxl_2f90a1c3
            documents:
              type: array
              items:
                $ref: "#/components/schemas/FlightDocument"
              description: "What each document the operation covers was last observed to be.
                Absent until the first probe. This is the proof of what
                happened: an operation has done its work when every document it
                covers has reached a terminal state, not when a refund record
                appears."
          description: The airline's record. It can show the tickets refunded while the
            money is still moving — that is the normal middle of a refund, not a
            discrepancy.
        money:
          type: object
          properties:
            amount:
              type: number
              description: "Deprecated: use `amount_money` instead. Alternative to `value` on
                some endpoints (the two never appear together); its scale
                depends on decimal_places. When this object carries
                decimal_places, amount is an INTEGER in minor units — divide by
                10 ** decimal_places (e.g. select_ancillaries
                total_with_ancillaries). When there is no decimal_places field,
                amount is a decimal in MAJOR units, safe to display as-is (e.g.
                trip and checkout totals)."
              deprecated: true
            value:
              type: integer
              description: "Deprecated: use `amount_money` instead. Integer amount in MINOR
                units, always paired with decimal_places — divide by 10 **
                decimal_places to display. Example: value 15977 with
                decimal_places 2 is 159.77 USD. Rendering this field directly
                shows prices 100x too high for 2-decimal currencies."
              example: 41250
              deprecated: true
            currency:
              type: string
              description: "Deprecated: use `amount_money` instead. ISO 4217 currency code."
              example: USD
              deprecated: true
            decimal_places:
              type: integer
              description: "Deprecated: use `amount_money` instead. Scale of the integer
                value/amount: display = integer / 10 ** decimal_places. Always
                sent alongside minor-unit amounts. Usually the ISO 4217 digits
                of the currency (2 for USD/EUR/GBP, 0 for JPY/KRW, 3 for
                BHD/JOD/KWD) but currency-converted prices can carry a different
                scale — ALWAYS use the decimal_places sent with the amount,
                never a hardcoded 2. Only if the field is genuinely absent on a
                value-shaped object, fall back to the ISO digits for the
                currency."
              example: 2
              deprecated: true
            display:
              type: string
              description: 'Deprecated: use `amount_money` instead. The same figure as a
                string ready to show: the ISO 4217 code, a space, then the
                amount, e.g. "USD 159.77". With decimal_places it is written at
                exactly that scale (value 1561500, JPY, decimal_places 2 is "JPY
                15615.00"); without, at the ISO digits of the currency. Show
                this; compute with the number. Absent when the figure is not
                money (a cancellation step expressed as a percent or a number of
                nights) or could not be read unambiguously.'
              example: USD 412.50
              deprecated: true
            amount_money:
              allOf:
                - $ref: "#/components/schemas/MoneyValue"
                - description: The figure being moved.
            direction:
              type: string
              description: Which way the money moves. `refund` on a cancellation.
              example: refund
            vehicle_state:
              type: string
              description: "How far the money itself has got, independently of the supplier:
                `reserved` (earmarked, nothing sent), `refund_pending`
                (submitted to the payment provider), `payout_initiated` and
                `payout_settled` (paid out to a third party), `paid` (it has
                reached the customer), `released` (earmark dropped, nothing
                owed), `refund_review` (a person at Jinko has to release it).
                Only `paid` and `payout_settled` mean the customer has the
                money."
              example: paid
            stripe_reference:
              type: string
              description: Deprecated. An internal payment reference.
              example: re_3UBIxK2eZvKYlo2C
              deprecated: true
          description: The refund and where it has got to. Read `vehicle_state` before
            telling a customer they have been refunded.
        operation_kind:
          allOf:
            - $ref: "#/components/schemas/FlightOperationKind"
            - description: Which operation ran — a refund under the fare rules (`cancel`) or a
                void of the original charge (`void`). The same field the preview
                quoted, so what was quoted and what ran compare directly.
    FlightRefundStatusRequest:
      type: object
      properties:
        booking_ref:
          type: string
          minLength: 1
          description: Jinko booking reference. Call get_booking first, then select its
            booked_item_id for servicing.
          example: JNK-A0AUR2
        booked_item_id:
          type: string
          pattern: ^itm_[a-z2-7]+$(?![\s\S])
          description: The booked item, from get_booking items[].booked_item_id. Preserved
            across exchanges. Omit only when the booking has exactly one item of
            the requested domain; otherwise a 409 returns items to choose from.
          example: itm_aaaaaaaaaaaaafhuxsdxpbzrbfz5hm3a
        last_name:
          type: string
          minLength: 1
          description: Required for guest lookup. A credential that owns the booking may
            omit it; ownership is checked by the platform.
          example: Doe
        provider_reference:
          type: string
          minLength: 1
          description: "Deprecated: name the booking with booking_ref and booked_item_id
            from get_booking. Names the booking instead of booking_ref and
            last_name, never beside it, and needs a credential that owns the
            booking. Accepted until 2027-04-30; a request that sends it is
            answered with `Deprecation` and `Sunset` headers."
          deprecated: true
        intent:
          $ref: "#/components/schemas/IntentInput"
        operation:
          type: string
          description: The "svc_…" handle from a commit, or from POST /v1/refund_commit.
          example: svc_01J7ZR5Q2KME8V4T
      required:
        - operation
      example:
        booking_ref: JNK-A0AUR2
        last_name: Doe
        operation: svc_01J7ZR5Q2KME8V4T
    WebhookCreatedResponse:
      type: object
      properties:
        id:
          type: number
          example: 42
        url:
          type: string
          example: https://partner.example.com/jinko/webhooks
        events:
          type: array
          items:
            type: string
          example:
            - booking.completed
        secret:
          type: string
          description: HMAC signing secret. Returned ONCE — store it securely; later reads
            show only a prefix.
          example: whsec_3f9a…
        status:
          type: string
          example: active
        created_at:
          type: string
          example: "2026-06-02T08:00:00Z"
      required:
        - id
        - url
        - events
        - secret
        - status
        - created_at
    CreateWebhookRequest:
      type: object
      properties:
        url:
          type: string
          format: uri
          example: https://partner.example.com/jinko/webhooks
        events:
          type: array
          items:
            $ref: "#/components/schemas/WebhookEvent"
          minItems: 1
          example:
            - booking.completed
            - booking.failed
            - booking.partial
      required:
        - url
        - events
      example:
        url: https://partner.example.com/jinko/webhooks
        events:
          - booking.completed
          - booking.failed
          - booking.partial
    WebhookListItem:
      type: object
      properties:
        id:
          type: number
          example: 42
        url:
          type: string
          example: https://partner.example.com/jinko/webhooks
        events:
          type: array
          items:
            type: string
          example:
            - booking.completed
            - booking.failed
        status:
          type: string
          example: active
        secret_prefix:
          type: string
          example: whsec_3f…
        created_at:
          type: string
          example: "2026-06-02T08:00:00Z"
        updated_at:
          type: string
          example: "2026-06-02T08:00:00Z"
      required:
        - id
        - url
        - events
        - status
        - secret_prefix
        - created_at
        - updated_at
    WebhookListResponse:
      type: object
      properties:
        webhooks:
          type: array
          items:
            $ref: "#/components/schemas/WebhookListItem"
      required:
        - webhooks
    WebhookDelivery:
      type: object
      properties:
        id:
          type: number
        event_id:
          type: string
          example: evt_1234_booking.completed
        event_type:
          type: string
          example: booking.completed
        booking_ref:
          type: string
          example: JNK-A7B3X9
        status:
          type: string
          example: delivered
        attempt_count:
          type: number
          example: 1
        last_http_status:
          type: number
          example: 200
        delivered_at:
          type: string
        created_at:
          type: string
    WebhookDetailResponse:
      type: object
      properties:
        webhook:
          $ref: "#/components/schemas/WebhookListItem"
        recent_deliveries:
          type: array
          items:
            $ref: "#/components/schemas/WebhookDelivery"
      required:
        - webhook
    WebhookDeleteResponse:
      type: object
      properties:
        message:
          type: string
          example: webhook deleted
      required:
        - message
    WebhookTestResponse:
      type: object
      properties:
        message:
          type: string
          example: test event enqueued
        delivery_id:
          type: number
          example: 101
        event_id:
          type: string
          example: evt_test_42_1780000000
      required:
        - message
    WebhookDeliveryDetail:
      type: object
      properties:
        id:
          type: number
        event_id:
          type: string
          example: evt_1234_booking.completed
        event_type:
          type: string
          example: booking.completed
        booking_ref:
          type: string
          nullable: true
          example: JNK-A7B3X9
        status:
          type: string
          description: "`pending` — queued for delivery; `delivered` — delivered
            successfully; `failed` — a retry is still scheduled; `exhausted` —
            the last attempt failed and exhausted_at is set."
          example: exhausted
        attempt_count:
          type: number
          example: 1
        last_http_status:
          type: number
          nullable: true
          example: 200
        delivered_at:
          type: string
          nullable: true
        created_at:
          type: string
        last_error:
          type: string
          nullable: true
          example: "non-2xx response: 503"
        updated_at:
          type: string
          example: "2026-10-08T11:20:40Z"
        exhausted_at:
          type: string
          nullable: true
          example: "2026-10-08T11:20:40Z"
        replay_count:
          type: integer
          example: 0
        payload:
          allOf:
            - $ref: "#/components/schemas/WebhookEventPayload"
            - nullable: true
      required:
        - last_error
        - updated_at
        - exhausted_at
        - replay_count
        - payload
      description: One event delivery to a webhook subscription, including its
        attempts and replay count. `payload` is the exact envelope sent, or null
        after it is purged 30 days after the delivery's last attempt or replay.
      example:
        id: 981
        event_id: evt_4471_booking.completed
        event_type: booking.completed
        booking_ref: JNK-8F3D21
        status: exhausted
        attempt_count: 8
        last_http_status: 503
        last_error: "non-2xx response: 503"
        created_at: "2026-10-08T10:02:11Z"
        updated_at: "2026-10-08T11:20:40Z"
        delivered_at: null
        exhausted_at: "2026-10-08T11:20:40Z"
        replay_count: 0
        payload:
          event: booking.completed
          event_id: evt_4471_booking.completed
          booking_ref: JNK-8F3D21
          status: confirmed
          occurred_at: "2026-10-08T10:02:11Z"
          livemode: true
    WebhookDeliveryListResponse:
      type: object
      properties:
        deliveries:
          type: array
          items:
            $ref: "#/components/schemas/WebhookDeliveryDetail"
        next_cursor:
          type: string
          nullable: true
          example: null
      required:
        - deliveries
        - next_cursor
    WebhookReplayResponse:
      type: object
      properties:
        delivery:
          $ref: "#/components/schemas/WebhookDeliveryDetail"
      required:
        - delivery
    WebhookReplayConflictResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - CONFLICT
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
        code:
          type: string
          enum:
            - delivery_in_progress
            - payload_purged
          description: The replay refusal reason. Absent for an unrecognised conflict.
      required:
        - error
  parameters: {}
paths:
  /health:
    get:
      tags:
        - system
      summary: Service health
      responses:
        "200":
          description: Service is up
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"
  /v1/flight_price_advice:
    post:
      tags:
        - Discovery
      summary: Accept a flight with its current price for price advice
      description: Accepts a flight with its current price and returns price advice.
        Available results compare the fare with typical fares for comparable
        flights and provide fixed 1-day and 3-day price forecasts, each with a
        forecasted price and estimated probabilities of an increase, decrease,
        or no change. Initial numeric coverage is one-adult, nonstop, USD;
        one-way, and round-trip with return_date; other structurally valid
        inputs return a reasoned unavailable result. The deterministic summary
        can be displayed without an LLM. The endpoint requires a verified jnk_
        API key and does not search, monitor, quote, or book flights. When the
        platform refuses the inputs, the answer is 400 or 422 `BAD_REQUEST` with
        the platform’s sentence; a 502 is a technical failure
        (`UPSTREAM_ERROR`).
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightPriceAdviceRequest"
      responses:
        "200":
          description: Computed flight price advice or a reasoned unavailable/not-ready
            result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightPriceAdviceResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_ai_search:
    post:
      tags:
        - Hotels
      summary: Search hotels from one sentence, with follow-ups
      description: "Send the traveller's request in one sentence. The answer comes
        within about 20 seconds with `200`: the hotels, or a question to answer
        in the same conversation. When the search takes longer, the answer is
        `202` with the early reply and a `Location` to read until the task ends.
        Continue the conversation with its `context_id`."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      servers: &a28
        - url: https://api.gojinko.com
          description: Production
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 200
            description: "Makes a retried message safe: a retry with the same key answers
              the first message again instead of sending a second one. Keys are
              scoped to the caller, not to the conversation, and the retried
              body is not compared: a different message needs a new key. 1–200
              characters."
          required: false
          name: Idempotency-Key
          in: header
        - schema:
            type: string
            maxLength: 200
            description: "`wait=N` (RFC 7240): answer after at most N seconds, never more
              than 20, with `202` and the early reply if the task has not ended
              by then. `wait=0` answers at once. Without it the wait is 20
              seconds. The wait applied is returned in `Preference-Applied`."
            example: wait=0
          required: false
          name: Prefer
          in: header
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelAiSearchRequest"
      responses:
        "200":
          description: "The task ended this turn; or, with `Accept: text/event-stream`,
            the turn as it happens."
          headers:
            Preference-Applied: &a27
              schema:
                type: string
              description: "The wait applied, as `wait=<seconds>`, when the request sent
                `Prefer: wait=N`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelAiSearchAnswer"
            text/event-stream:
              schema:
                type: string
                description: "Server-Sent Events, one per task event: `id` is its sequence
                  number (send it back as `Last-Event-ID` to resume), `event` is
                  `task.status` (`status` `submitted` or `working`),
                  `agent.message` (the early reply first), `hotels.page`, or
                  `task.completed` / `task.input_required` / `task.failed` /
                  `task.canceled` / `task.expired` for the status that ends the
                  turn; `data` is JSON and carries `task_id` and `context_id`.
                  The stream ends with the turn, or after 45 seconds: resume it
                  with the `Last-Event-ID` of the last event received."
        "202":
          description: "The search is still running: the early reply. Read `Location`
            after Retry-After."
          headers:
            Location:
              schema:
                type: string
              description: The task to read for the final answer.
            Retry-After:
              schema:
                type: string
              description: Seconds to wait before reading the task again.
            Preference-Applied: *a27
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelAiSearchAnswer"
        "400":
          description: "Bad request: malformed JSON, or an invalid header such as a
            reserved `X-End-User-Id`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a29
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "403":
          description: The key is valid but not granted the `search_live` scope, or the
            account is limited to cached searches. **`FORBIDDEN`** — The
            credential is valid, and this request is refused anyway. Do not
            rotate the key — it is working. Check that it is entitled to this
            operation, and on this environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a30
                error:
                  code: FORBIDDEN
                  message: This API key is not granted the "search_live" scope required by this
                    endpoint
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a31
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a32
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers: &a33
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a34
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a35
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers: &a36
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a37
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a38
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_ai_search/tasks/{task_id}:
    get:
      tags:
        - Hotels
      summary: Read a hotel AI search task
      description: "The task's answer now: `working` with the early reply, or the
        final answer."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      servers: *a28
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 100
            example: atk_example
          required: true
          name: task_id
          in: path
      responses:
        "200":
          description: The task.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelAiSearchAnswer"
        "400":
          description: "Bad request: an invalid header, such as a reserved `X-End-User-Id`
            (`user_…`, `org_…`)."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: &a39
                error:
                  code: BAD_REQUEST
                  message: X-End-User-Id must be an opaque, tenant-scoped id; WorkOS-shaped ids
                    (user_…, org_…) are not allowed.
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a29
        "403":
          description: The key is valid but not granted the `search_live` scope, or the
            account is limited to cached searches. **`FORBIDDEN`** — The
            credential is valid, and this request is refused anyway. Do not
            rotate the key — it is working. Check that it is entitled to this
            operation, and on this environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a30
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a31
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a32
        "429":
          description: Rate limit or quota exceeded
          headers: *a33
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a34
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a35
        "503":
          description: No travel provider can serve the request right now
          headers: *a36
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a37
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a38
  /v1/hotel_ai_search/tasks/{task_id}/events:
    get:
      tags:
        - Hotels
      summary: Stream a hotel AI search task's events
      description: "The task's events as Server-Sent Events, from the start or after
        `Last-Event-ID`. The stream ends when the task ends its turn, or after
        45 seconds: reconnect with the `Last-Event-ID` of the last event
        received."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      servers: *a28
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 100
            example: atk_example
          required: true
          name: task_id
          in: path
        - schema:
            type: string
            maxLength: 20
            description: The `id` of the last event received.
            example: "7"
          required: false
          name: Last-Event-ID
          in: header
      responses:
        "200":
          description: The events.
          content:
            text/event-stream:
              schema:
                type: string
                description: "Server-Sent Events, one per task event: `id` is its sequence
                  number (send it back as `Last-Event-ID` to resume), `event` is
                  `task.status` (`status` `submitted` or `working`),
                  `agent.message` (the early reply first), `hotels.page`, or
                  `task.completed` / `task.input_required` / `task.failed` /
                  `task.canceled` / `task.expired` for the status that ends the
                  turn; `data` is JSON and carries `task_id` and `context_id`.
                  The stream ends with the turn, or after 45 seconds: resume it
                  with the `Last-Event-ID` of the last event received."
        "400":
          description: "Bad request: an invalid header, such as a reserved `X-End-User-Id`
            (`user_…`, `org_…`)."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a39
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a29
        "403":
          description: The key is valid but not granted the `search_live` scope, or the
            account is limited to cached searches. **`FORBIDDEN`** — The
            credential is valid, and this request is refused anyway. Do not
            rotate the key — it is working. Check that it is entitled to this
            operation, and on this environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a30
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a31
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a32
        "429":
          description: Rate limit or quota exceeded
          headers: *a33
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a34
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a35
        "503":
          description: No travel provider can serve the request right now
          headers: *a36
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a37
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a38
  /v1/hotel_ai_search/tasks/{task_id}:cancel:
    post:
      tags:
        - Hotels
      summary: Cancel a hotel AI search task
      description: Cancels a task that has not ended. A task that already ended
        answers `409` `CONFLICT`.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      servers: *a28
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 100
            example: atk_example
          required: true
          name: task_id
          in: path
      responses:
        "200":
          description: The task, now `canceled`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelAiSearchAnswer"
        "400":
          description: "Bad request: an invalid header, such as a reserved `X-End-User-Id`
            (`user_…`, `org_…`)."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a39
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a29
        "403":
          description: The key is valid but not granted the `search_live` scope, or the
            account is limited to cached searches. **`FORBIDDEN`** — The
            credential is valid, and this request is refused anyway. Do not
            rotate the key — it is working. Check that it is entitled to this
            operation, and on this environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a30
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a31
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a32
        "429":
          description: Rate limit or quota exceeded
          headers: *a33
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a34
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a35
        "503":
          description: No travel provider can serve the request right now
          headers: *a36
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a37
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example: *a38
  /v1/find_destination:
    post:
      tags:
        - Discovery
      summary: Discover travel destinations accessible from your departure airports
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FindDestinationRequest"
      responses:
        "200":
          description: Matching destinations
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FindDestinationResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_calendar:
    post:
      tags:
        - Discovery
      summary: Search flights between a known origin and destination for flexible dates
      description: "`limit` caps the globally sorted itinerary list across the full
        matching date range; it does not reserve one result for each date pair.
        With the default `sort_by: lowest`, a limited response contains the
        cheapest itineraries overall, so an omitted date pair does not by itself
        mean that date is missing from the cache. Use `find_dates` for date-pair
        coverage."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightDiscoveryRequest"
      responses:
        "200":
          description: Matching itineraries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightCalendarResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/find_dates:
    post:
      tags:
        - Discovery
      summary: Best date options for a route — the cheapest itinerary per date pair,
        spread across the window
      description: Takes the same request as flight_calendar and returns one cheapest
        itinerary per (departure, return) date pair, for up to `limit` date
        pairs (default 20) spread across the requested departure window, so you
        see a diverse set of date options rather than near-adjacent cheapest
        days. Cache-backed; never live-prices.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightDiscoveryRequest"
      responses:
        "200":
          description: Best date options (one itinerary per date-pair)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightCalendarResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/lowest_fare:
    post:
      tags:
        - Discovery
      summary: Cheapest fares for a fixed route + date — up to ten itineraries,
        cheapest first
      description: Takes the same request as flight_calendar but, for a fixed origin,
        destination, and date, returns up to ten itineraries sorted
        cheapest-first; `limit` is not applied on this route. The fixed-date
        counterpart of flight_calendar. Cache-backed; never live-prices.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightDiscoveryRequest"
      responses:
        "200":
          description: Cheapest itineraries for the route + date, lowest-first
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightCalendarResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_search:
    post:
      tags:
        - Pricing & booking
      summary: Get live flight pricing — search by route, or re-price a known offer
      description: "Two modes: **search** — provide `origin` + `destination` +
        `departure_date` to price a route; or **price-check** — provide only
        `offer_token` to re-price a specific offer from a discovery endpoint.
        Exactly one mode per request."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightSearchRequest"
      responses:
        "200":
          description: "Priced offers. Every filter that narrows the results (cabin,
            stops, price, carriers, times, connections, fare conditions,
            aircraft) is applied exactly as sent: no returned offer breaks one.
            Options that widen a search (alternate or nearby airports) are
            searched where available. A search that completes and matches
            nothing is also a 200: `offers` is empty, `result` is `no_matches`
            and the body carries a recovery `instruction`. A search that could
            not be completed answers an error (`UPSTREAM_REJECTED`,
            `UPSTREAM_ERROR`, `UPSTREAM_UNAVAILABLE` or `UPSTREAM_TIMEOUT`)
            rather than an empty list. Offers that were found are returned even
            when part of the search could not be completed."
          headers:
            X-Jinko-Result:
              deprecated: true
              required: false
              description: "Deprecated: read `result` in the body. Sent for empty searches
                with result no_matches."
              schema:
                type: string
                example: no_matches
            X-Jinko-Instruction:
              deprecated: true
              required: false
              description: "Deprecated: read `instruction` in the body. Sent for empty
                searches with result no_matches."
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightSearchResponse"
        "400":
          description: The request was malformed or failed validation (search and price
            check alike). When a supplier declined the request, `error.message`
            is “The request was declined for these inputs. Check the dates,
            places and travellers, then retry.” **`BAD_REQUEST`** — The request
            was malformed or failed validation. Fix the request as the message
            describes; retrying it unchanged cannot succeed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: The request was declined for these inputs. Check the dates, places and
                    travellers, then retry.
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/price_monitoring:
    post:
      tags:
        - Discovery
      summary: Monitor price for a specific origin, destination, and dates pair
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PriceMonitoringRequest"
      responses:
        "200":
          description: Cheapest cached itinerary, or stale on a cache miss
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PriceMonitoringResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_schedule:
    post:
      tags:
        - Discovery
      summary: Flights observed between two places on exact dates (no price)
      description: "Returns the trips the flight catalog has observed for one origin,
        one destination and an exact date pair. `trip_type` says which kind:
        `oneway` (no `return_date`) or `roundtrip` (`return_date` required); a
        round trip is an outbound + inbound pairing that was actually observed
        together, never a combination built from two one-ways. The answer
        carries no price, and `last_seen` is when a fare search last observed
        the trip — not a statement that it can be booked. Results are paged:
        send `pagination.next_page_token` back as `page_token` until it is
        empty."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightScheduleRequest"
      responses:
        "200":
          description: Observed trips; `trips` is empty when nothing matches
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightScheduleResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/trip:
    post:
      tags:
        - Pricing & booking
      summary: "Create and manage a trip: add or remove items and set travelers"
      description: Creates or edits a trip without starting pricing. A new item has no
        price until it is successfully quoted. Call POST /v1/checkout to start
        pricing and wait for a checkout result. Polling GET /v1/trip/{trip_id}
        after creation does not start pricing.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TripRequest"
      responses:
        "200":
          description: The trip
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TripResponse"
        "400":
          description: The request was refused. Invalid traveller names at
            `upsert_travelers` are refused with `BAD_REQUEST` and `error.field`
            naming the traveller. **`BAD_REQUEST`** — The request was malformed
            or failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "The trip refused the write, and nothing was changed — `updated_at`
            is untouched. **`TRIP_EXPIRED`** — The trip lapsed (24 hours without
            activity) and no longer accepts writes. Start a new trip and add the
            items again. A lapsed trip cannot be revived.
            **`TRIP_STATE_CONFLICT`** — The trip is in a state that refuses this
            operation: payment already started (`fulfilling`, `fulfilled`,
            `partially_fulfilled`), or it is `cancelled` or `failed`. Read
            `status` and act on it: read the trip to find the booking that
            already exists, or start a new trip. Nothing was written.
            **`CONFLICT`** — The resource's current state refuses the operation.
            Re-read the resource and act on what it says — never retry blindly."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/TripStateResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: TRIP_EXPIRED
                  message: This trip expired after 24 hours without activity and cannot be
                    modified.
                  doc_url: https://docs.gojinko.com/concepts/errors
                status: expired
        "410":
          description: "The offer named in the request is no longer available, or another
            resource the request names is gone. Tell the two apart by
            `error.code`. **`OFFER_EXPIRED`** — The search offer is no longer
            usable: its token expired, or the supplier rejected it as expired or
            missing during pricing. No payable quote was established. Search
            again, replace the unavailable item using the latest search result,
            and check out promptly. Show that the flight offer is no longer
            available; do not describe this as an established quote expiring
            (QUOTE_EXPIRED). **`GONE`** — The resource this request names
            existed and no longer does. Re-acquire it — search again, or check
            out again to re-quote — then retry with the new identifier.
            Repeating this request with the same one cannot succeed."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "422":
          description: "The request failed validation. Tell the causes apart by
            `error.code`. **`BAD_REQUEST`** — The request was malformed or
            failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed. **`INVALID_PHONE_NUMBER`** — A
            phone number is not in international format: it has no leading `+`
            and country code, is not a possible number, or carries an extension.
            Nothing was written. Resend the number with a leading `+` and
            country code, for example `+12025550147`. Spaces, hyphens, dots and
            parentheses are accepted and removed."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: INVALID_PHONE_NUMBER
                  message: phone number must be in international format with a leading + and
                    country code, for example +12025550147
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/trip/{trip_id}:
    get:
      tags:
        - Pricing & booking
      summary: Fetch the full lifecycle state of a trip — items, travelers, quote,
        fulfillment, and any booking references
      description: Reads the latest trip state without starting pricing. After
        checkout fails, quote.status can be failed, with failure_reason and
        failure_message when available. A failed quote has no payment
        expires_at. Never treat a missing item price or total_amount as zero.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
          required: true
          name: trip_id
          in: path
      responses:
        "200":
          description: The trip
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetTripResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/trip/{trip_id}/ancillaries:
    get:
      tags:
        - Pricing & booking
      summary: List purchasable ancillaries for a trip (no checkout)
      description: >-
        Returns the available ancillaries for a trip without generating a
        checkout URL. A price quote runs automatically to retrieve the ancillary
        catalog and is reused while valid.


        Responds **200** with `status: "ready"` and `items[]` when the quote is
        complete. If the quote is still being priced it responds **202** with
        `status: "pricing"` and a `Retry-After` header — poll the same URL until
        it returns 200. Never returns a checkout URL.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
          required: true
          name: trip_id
          in: path
      responses:
        "200":
          description: 'Ancillaries ready: `status: "ready"` with `items[]`.'
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TripAncillariesResponse"
        "202":
          description: 'The quote is still being priced: `status: "pricing"`. Poll the
            same URL after Retry-After.'
          headers:
            Retry-After:
              schema:
                type: string
              description: Polling delay supplied by the service.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TripAncillariesResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/select_ancillaries:
    post:
      tags:
        - Pricing & booking
      summary: Select ancillaries (baggage, seats, meals) for a trip item
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AncillaryRequest"
      responses:
        "200":
          description: Updated ancillary selection
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AncillaryResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/checkout:
    post:
      tags:
        - Pricing & booking
      summary: Checkout a trip — returns a checkout URL the user opens to pay, plus
        the Shared Payment Token params an agent can use to pay programmatically
      description: "Starts pricing when no valid quote exists and waits server-side
        for up to about 55 seconds. If the quote is still being priced, answers
        503 QUOTE_PENDING with Retry-After; calling checkout again picks up the
        same quote. A successful response contains the quoted prices and
        checkout details; no GET trip polling is required first. A supplier
        offer rejected as expired or missing during pricing returns 410
        OFFER_EXPIRED, even when no quote has ever succeeded. Search again and
        replace the item. QUOTE_EXPIRED instead describes an established quote
        that can no longer be used: its deadline passed, or the trip's travelers
        changed after it was priced (`reason: travelers_changed`). Call checkout
        again to re-quote."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CheckoutRequest"
      responses:
        "200":
          description: "Checkout result: the priced trip and how to pay for it"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutResponse"
        "400":
          description: The request was refused. Invalid traveller names are refused with
            `BAD_REQUEST` and `error.field` naming the traveller.
            **`BAD_REQUEST`** — The request was malformed or failed validation.
            Fix the request as the message describes; retrying it unchanged
            cannot succeed. **`CURRENCY_UNSUPPORTED`** — The requested currency
            is not supported for this operation. Re-run the search in a
            supported currency. Agent payment supports `USD` or `EUR`, depending
            on the partner's Stripe account binding; a trip in a currency the
            partner does not accept carries no `agent_spt_params`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "The checkout could not proceed against the current state of the
            trip. Tell the causes apart by `error.code`. **`CONFLICT`** — The
            resource's current state refuses the operation. Re-read the resource
            and act on what it says — never retry blindly. **`TRIP_EXPIRED`** —
            The trip lapsed (24 hours without activity) and no longer accepts
            writes. Start a new trip and add the items again. A lapsed trip
            cannot be revived. **`TRIP_STATE_CONFLICT`** — The trip is in a
            state that refuses this operation: payment already started
            (`fulfilling`, `fulfilled`, `partially_fulfilled`), or it is
            `cancelled` or `failed`. Read `status` and act on it: read the trip
            to find the booking that already exists, or start a new trip.
            Nothing was written. **`OFFER_UNAVAILABLE`** — The provider can no
            longer quote this offer. Emitted today when the hotel supplier has
            no rate for your occupancy at quote time, and at checkout when a
            flight fare cannot be priced for the trip's travellers: the fare is
            not sold for them, or the airline declines to price it. Search again
            for the occupancy or the travellers you intend to book and pick an
            offer that covers them; this one cannot be quoted at any price."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/TripStateResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example: &a40
                error:
                  code: CONFLICT
                  message: The checkout could not proceed against the current state of the trip.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: "The selected offer could not be priced, the established quote can
            no longer be used (`QUOTE_EXPIRED`, with `reason: travelers_changed`
            when the trip's travelers changed after it was priced), or another
            resource the request names is gone. Tell the causes apart by
            `error.code`. **`OFFER_EXPIRED`** — The search offer is no longer
            usable: its token expired, or the supplier rejected it as expired or
            missing during pricing. No payable quote was established. Search
            again, replace the unavailable item using the latest search result,
            and check out promptly. Show that the flight offer is no longer
            available; do not describe this as an established quote expiring
            (QUOTE_EXPIRED). **`GONE`** — The resource this request names
            existed and no longer does. Re-acquire it — search again, or check
            out again to re-quote — then retry with the new identifier.
            Repeating this request with the same one cannot succeed.
            **`QUOTE_EXPIRED`** — The quote can no longer be paid, so payment
            was refused before any payment object was created: either it passed
            its `expires_at`, or the trip's travelers changed after it was
            priced (`reason: travelers_changed`; `expires_at` is then the
            refusal instant). A typed payment refused this way also carries
            `payment_error` and `recovery`. Call `POST /v1/checkout` again on
            the same trip — it re-quotes — then mint a new Shared Payment Token
            against the new `agent_spt_params` and submit that against the new
            `quote_id`. Nothing was charged."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/QuoteExpiredResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
        "422":
          description: "The trip is not complete enough to check out. Tell the causes
            apart by `error.code`. **`BAD_REQUEST`** — The request was malformed
            or failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed. **`MISSING_CUSTOMER_DETAILS`**
            — The trip is missing details the booking needs: no travelers, a
            contact without both an email and a phone, or passenger documents a
            carrier requires (see `required_attributes` on the trip item). Send
            `upsert_travelers` with the travelers, a contact, and the fields
            named in `missing_fields`, then check out again."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/MissingCustomerDetailsResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example: &a41
                error:
                  code: MISSING_CUSTOMER_DETAILS
                  message: "the provider requires details this booking has not collected — flight:
                    passport_number, passport_expiry, passport_country,
                    nationality"
                  doc_url: https://docs.gojinko.com/concepts/errors
                missing_fields:
                  - nationality
                  - passport_country
                  - passport_expiry
                  - passport_number
                missing_by_domain:
                  flight:
                    - passport_number
                    - passport_expiry
                    - passport_country
                    - nationality
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: The quote is still being priced, or an upstream service is
            unavailable. **`QUOTE_PENDING`** — The trip's quote is still being
            priced. Call `POST /v1/checkout` again after the interval in
            `Retry-After`; the call picks up the same quote and answers with the
            checkout once it is priced. **`UPSTREAM_UNAVAILABLE`** — No provider
            can serve the request right now, for a reason that is not the
            request. Retry unchanged after the interval in `Retry-After`.
          headers: &a42
            Retry-After:
              description: Seconds to wait before calling checkout again to pick up the same
                quote.
              schema:
                type: string
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - type: object
                    properties:
                      retry_after_seconds:
                        type: integer
                        minimum: 0
                        exclusiveMinimum: true
                      quote_id:
                        type: string
                        description: The quote being priced; checkout called again picks up the same
                          one.
                        example: "2097152"
                      quoted_cart_id:
                        type: number
                        description: "Deprecated: use `quote_id` instead. The same quote as an integer."
                        deprecated: true
        "504":
          description: The upstream service did not answer before the deadline.
            **`UPSTREAM_TIMEOUT`** — A travel provider did not answer in time.
            Retry a read unchanged. Before repeating a request that changes
            something, read the resource's state because the operation may still
            have completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /v1/book:
    post:
      tags:
        - Pricing & booking
      summary: DEPRECATED — use /checkout. Alias retained for backward compatibility.
      description: 'Deprecated alias of `POST /v1/checkout`, kept so existing
        integrators keep working through the rename. Every response carries
        `Deprecation: true`, `Sunset: Fri, 30 Apr 2027 23:59:59 GMT` and `Link:
        </v1/checkout>; rel="successor-version"`, so the removal date is
        readable from your own logs. Behaviour is identical to `/v1/checkout`
        until then; switch the path and nothing else changes. Pricing is
        synchronous: it waits for success or failure, and can return 410
        OFFER_EXPIRED when a supplier offer cannot be priced, before any valid
        quote exists. See https://docs.gojinko.com/concepts/versioning.'
      deprecated: true
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CheckoutRequest"
      responses:
        "200":
          description: "Checkout result: the priced trip and how to pay for it"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutResponse"
        "400":
          description: The request was refused. Invalid traveller names are refused with
            `BAD_REQUEST` and `error.field` naming the traveller.
            **`BAD_REQUEST`** — The request was malformed or failed validation.
            Fix the request as the message describes; retrying it unchanged
            cannot succeed. **`CURRENCY_UNSUPPORTED`** — The requested currency
            is not supported for this operation. Re-run the search in a
            supported currency. Agent payment supports `USD` or `EUR`, depending
            on the partner's Stripe account binding; a trip in a currency the
            partner does not accept carries no `agent_spt_params`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "The checkout could not proceed against the current state of the
            trip. Tell the causes apart by `error.code`. **`CONFLICT`** — The
            resource's current state refuses the operation. Re-read the resource
            and act on what it says — never retry blindly. **`TRIP_EXPIRED`** —
            The trip lapsed (24 hours without activity) and no longer accepts
            writes. Start a new trip and add the items again. A lapsed trip
            cannot be revived. **`TRIP_STATE_CONFLICT`** — The trip is in a
            state that refuses this operation: payment already started
            (`fulfilling`, `fulfilled`, `partially_fulfilled`), or it is
            `cancelled` or `failed`. Read `status` and act on it: read the trip
            to find the booking that already exists, or start a new trip.
            Nothing was written. **`OFFER_UNAVAILABLE`** — The provider can no
            longer quote this offer. Emitted today when the hotel supplier has
            no rate for your occupancy at quote time, and at checkout when a
            flight fare cannot be priced for the trip's travellers: the fare is
            not sold for them, or the airline declines to price it. Search again
            for the occupancy or the travellers you intend to book and pick an
            offer that covers them; this one cannot be quoted at any price."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/TripStateResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example: *a40
        "410":
          description: "The selected offer could not be priced, the established quote can
            no longer be used (`QUOTE_EXPIRED`, with `reason: travelers_changed`
            when the trip's travelers changed after it was priced), or another
            resource the request names is gone. Tell the causes apart by
            `error.code`. **`OFFER_EXPIRED`** — The search offer is no longer
            usable: its token expired, or the supplier rejected it as expired or
            missing during pricing. No payable quote was established. Search
            again, replace the unavailable item using the latest search result,
            and check out promptly. Show that the flight offer is no longer
            available; do not describe this as an established quote expiring
            (QUOTE_EXPIRED). **`GONE`** — The resource this request names
            existed and no longer does. Re-acquire it — search again, or check
            out again to re-quote — then retry with the new identifier.
            Repeating this request with the same one cannot succeed.
            **`QUOTE_EXPIRED`** — The quote can no longer be paid, so payment
            was refused before any payment object was created: either it passed
            its `expires_at`, or the trip's travelers changed after it was
            priced (`reason: travelers_changed`; `expires_at` is then the
            refusal instant). A typed payment refused this way also carries
            `payment_error` and `recovery`. Call `POST /v1/checkout` again on
            the same trip — it re-quotes — then mint a new Shared Payment Token
            against the new `agent_spt_params` and submit that against the new
            `quote_id`. Nothing was charged."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/QuoteExpiredResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
        "422":
          description: "The trip is not complete enough to check out. Tell the causes
            apart by `error.code`. **`BAD_REQUEST`** — The request was malformed
            or failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed. **`MISSING_CUSTOMER_DETAILS`**
            — The trip is missing details the booking needs: no travelers, a
            contact without both an email and a phone, or passenger documents a
            carrier requires (see `required_attributes` on the trip item). Send
            `upsert_travelers` with the travelers, a contact, and the fields
            named in `missing_fields`, then check out again."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/MissingCustomerDetailsResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example: *a41
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: The quote is still being priced, or an upstream service is
            unavailable. **`QUOTE_PENDING`** — The trip's quote is still being
            priced. Call `POST /v1/checkout` again after the interval in
            `Retry-After`; the call picks up the same quote and answers with the
            checkout once it is priced. **`UPSTREAM_UNAVAILABLE`** — No provider
            can serve the request right now, for a reason that is not the
            request. Retry unchanged after the interval in `Retry-After`.
          headers: *a42
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - type: object
                    properties:
                      retry_after_seconds:
                        type: integer
                        minimum: 0
                        exclusiveMinimum: true
                      quote_id:
                        type: string
                        description: The quote being priced; checkout called again picks up the same
                          one.
                        example: "2097152"
                      quoted_cart_id:
                        type: number
                        description: "Deprecated: use `quote_id` instead. The same quote as an integer."
                        deprecated: true
        "504":
          description: The upstream service did not answer before the deadline.
            **`UPSTREAM_TIMEOUT`** — A travel provider did not answer in time.
            Retry a read unchanged. Before repeating a request that changes
            something, read the resource's state because the operation may still
            have completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /v1/agent_payment/submit:
    post:
      tags:
        - Pricing & booking
      summary: Submit a typed SPT payment with Idempotency-Key, or a legacy flat
        Shared Payment Token
      description: "Typed submissions require a jnk_ API key via X-API-Key
        (ApiKeyAuth) or Authorization: Bearer (BearerAuth), a tenant-bound
        booking scope, quote_id and Idempotency-Key, and return a
        PaymentAttemptOutcome (200 known outcome / 202 pending). OAuth/JWT
        bearer tokens are supported only for the legacy flat token body, which
        keeps its existing authorization response. Request bodies are limited to
        16 KiB."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            pattern: ^[ -~]+$(?![\s\S])
            description: "Required on a typed submission (a body with `payment`); without it
              the request is refused with 400 `CREDENTIAL_FORMAT_INVALID`.
              Ignored on the legacy body. 1–255 printable ASCII characters.
              Reuse only for the same payment submission: the same key with the
              same body replays the first outcome, with a different body it is
              refused."
          required: false
          name: Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - $ref: "#/components/schemas/TypedAgentPaymentSubmitRequest"
                - $ref: "#/components/schemas/AgentPaymentSubmitRequest"
      responses:
        "200":
          description: Legacy authorization result or typed payment outcome
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/PaymentAttemptOutcome"
                  - $ref: "#/components/schemas/AgentPaymentSubmitResponse"
        "202":
          description: Payment accepted and pending; poll the attempt after Retry-After.
          headers:
            Retry-After:
              schema:
                type: string
              description: Polling delay supplied by the service.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentAttemptOutcome"
        "400":
          description: Payment credential format or validity refusal.
            **`CREDENTIAL_FORMAT_INVALID`** — The typed payment body or
            Idempotency-Key has an invalid format. Correct the named field and
            resubmit with a valid Idempotency-Key.
            **`PAYMENT_CREDENTIAL_INVALID`** — The payment credential is
            invalid. Follow recovery.action and supply a replacement credential
            when required. **`BAD_REQUEST`** — The request was malformed or
            failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentRefusalResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "403":
          description: This payment type is not enabled or access is forbidden.
            **`PAYMENT_TYPE_NOT_ENABLED`** — This payment type is not enabled
            for the caller. Choose a type advertised in accepted_payment_types
            or contact support. **`FORBIDDEN`** — The credential is valid, and
            this request is refused anyway. Do not rotate the key — it is
            working. Check that it is entitled to this operation, and on this
            environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentRefusalResponse"
        "404":
          description: The trip, or the `quote_id` among its quotes, was not found.
            Nothing was charged. **`NOT_FOUND`** — No resource with that
            identifier is visible to this key. Check the identifier. A trip or
            booking belongs to the key that created it.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Payment submission conflicts with an existing attempt.
            **`TRIP_OWNED_BY_OTHER_PAYMENT`** — Another payment attempt owns
            this trip. Read the existing attempt and follow its recovery action
            before paying again. **`IDEMPOTENCY_KEY_REUSED`** — The idempotency
            key was already used for a different submission. Reuse the original
            request with this key, or use a new key for a new submission.
            **`ATTEMPT_IN_PROGRESS`** — A payment attempt is already in
            progress. Poll the existing attempt and follow recovery.action.
            **`ATTEMPT_TERMINAL`** — This payment attempt has reached a terminal
            state. Read its outcome and follow recovery.action before starting
            another attempt.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentRefusalResponse"
        "410":
          description: "The locked quote has expired, so nothing was redeemed and no
            payment object was created — or the resource the request names is
            gone. Tell the two apart by `error.code`. **`QUOTE_EXPIRED`** — The
            quote can no longer be paid, so payment was refused before any
            payment object was created: either it passed its `expires_at`, or
            the trip's travelers changed after it was priced (`reason:
            travelers_changed`; `expires_at` is then the refusal instant). A
            typed payment refused this way also carries `payment_error` and
            `recovery`. Call `POST /v1/checkout` again on the same trip — it
            re-quotes — then mint a new Shared Payment Token against the new
            `agent_spt_params` and submit that against the new `quote_id`.
            Nothing was charged. **`GONE`** — The resource this request names
            existed and no longer does. Re-acquire it — search again, or check
            out again to re-quote — then retry with the new identifier.
            Repeating this request with the same one cannot succeed."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/QuoteExpiredResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/PaymentRefusalResponse"
              example:
                error:
                  code: QUOTE_EXPIRED
                  message: The quote behind this checkout expired at 2026-09-04T12:39:56Z.
                  doc_url: https://docs.gojinko.com/concepts/errors
                expires_at: "2026-09-04T12:39:56Z"
                quote_id: "2097152"
                reason: travelers_changed
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: Payment temporarily unavailable. **`TEMPORARILY_UNAVAILABLE`** —
            Payment submission is temporarily unavailable. Wait for Retry-After
            when provided and follow recovery.action.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentRefusalResponse"
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/trip/{trip_id}/payment_attempts/{payment_attempt_id}:
    get:
      tags:
        - Pricing & booking
      summary: Read a payment attempt outcome
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
          required: true
          name: trip_id
          in: path
        - schema:
            type: string
          required: true
          name: payment_attempt_id
          in: path
      responses:
        "200":
          description: Payment attempt outcome
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentAttemptOutcome"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "403":
          description: Payment attempt access forbidden. **`FORBIDDEN`** — The credential
            is valid, and this request is refused anyway. Do not rotate the key
            — it is working. Check that it is entitled to this operation, and on
            this environment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_search:
    post:
      tags:
        - Hotels
      summary: Search live hotel inventory and rates
      description: "The search is described by the JSON body alone. The two query
        parameters earlier contract versions accepted to switch hotel inventory
        sources on or off are deprecated: they are accepted and ignored until
        2027-04-30, and the platform chooses which inventory to search. A
        request that sends one is answered with the `Deprecation`, `Sunset` and
        `Link` headers."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelSearchRequest"
      responses:
        "200":
          description: Matching hotels
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelSearchResponse"
        "400":
          description: The request was malformed or failed validation. When a supplier
            declined the request, `error.message` is “The request was declined
            for these inputs. Check the dates, places and travellers, then
            retry.” **`BAD_REQUEST`** — The request was malformed or failed
            validation. Fix the request as the message describes; retrying it
            unchanged cannot succeed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: The request was declined for these inputs. Check the dates, places and
                    travellers, then retry.
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: The request failed validation, or named a destination the platform
            could not confidently resolve. Tell the causes apart by
            `error.code`. **`BAD_REQUEST`** — The request was malformed or
            failed validation. Fix the request as the message describes;
            retrying it unchanged cannot succeed.
            **`HOTEL_NAME_LOW_CONFIDENCE`** — A `hotel_name` lookup found no
            exact match, only close candidates none of which clearly wins. Read
            `error.top_candidates` (closest first). If the top one is an obvious
            match, retry with its `hotel_id`; if several fit, ask the user which
            one they meant — never say there is no such hotel.
            **`DESTINATION_LOW_CONFIDENCE`** — A `city_name` + `country_code`
            search found no exact catalog city, only close candidates none of
            which clearly wins. Read `error.top_candidates` (closest first). If
            the top one is an obvious typo fix, confirm and retry with
            `error.suggested_retry.destination`; if several fit, ask the user
            which city they meant — never say there are no hotels in the
            requested city.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/HotelNameLowConfidenceResponse"
                  - $ref: "#/components/schemas/DestinationLowConfidenceResponse"
                  - $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: DESTINATION_LOW_CONFIDENCE
                  message: 'no confident city match for "Sain Malo" in FR (closest: "Saint Malo",
                    FR at 0.75)'
                  top_candidates:
                    - city: Saint Malo
                      country_code: FR
                      hotel_count: 326
                      score: 0.75
                  suggested_retry:
                    destination:
                      city_name: Saint Malo
                      country_code: FR
                    rationale: the closest catalog city to the requested name; retry with it, or ask
                      the user when the candidates differ
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_details/{hotel_id}:
    get:
      tags:
        - Hotels
      summary: Fetch rich metadata (gallery, facilities, policies, per-room details)
        for a single hotel
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: "The `hotel_id` of a hotel from hotel_search, passed exactly as
              received and URL-encoded as one path segment. It is opaque: do not
              parse or build it."
            example: lp1d2c3
          required: true
          name: hotel_id
          in: path
        - schema:
            type: string
          required: false
          name: checkin
          in: query
        - schema:
            type: string
          required: false
          name: checkout
          in: query
      responses:
        "200":
          description: Hotel detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelDetailsResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_reviews/{hotel_id}:
    get:
      tags:
        - Hotels
      summary: Guest review summary and recent reviews for a single hotel
      description: "Use after hotel_search or hotel_details, when the user wants to
        know what guests say about a hotel or how it scores on cleanliness,
        location or staff. Returns the overall guest score and review count, a
        summary of what guests praise and criticise, a score per category, and a
        page of recent reviews, newest first: headline, score, pros/cons, date
        and language for each. The review source is not attributed."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: "The `hotel_id` of a hotel from hotel_search, or the `id`
              hotel_details returns, passed exactly as received and URL-encoded
              as one path segment. It is opaque: do not parse or build it."
            example: lp1d2c3
          required: true
          name: hotel_id
          in: path
        - schema:
            type: integer
            minimum: 1
            maximum: 50
            description: Reviews per page, 1 to 50. Default 10.
            example: 10
          required: false
          name: limit
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            maximum: 2147483647
            description: Reviews to skip before this page. Default 0.
            example: 0
          required: false
          name: offset
          in: query
      responses:
        "200":
          description: Hotel reviews
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelReviewsResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/best_price_guarantee:
    post:
      tags:
        - Hotels
      summary: "Best Price Guarantee: ask for a hotel offer at a lower price found
        elsewhere"
      description: "Submit a hotel offer from `POST /v1/hotel_search` with the lower
        price the traveller found for the same stay on another site: the link, a
        screenshot address and the total payable at booking, in the currency of
        the offer. The submission is reviewed in the background and this call
        answers `pending` with an `id`, or the result when `wait_seconds` let it
        finish in time. The answer carries the state of the request in `status`:
        `pending` while the review runs, then `offered` with the new offer, or
        `declined` with the reason. A decline is a 200: it is an answer, not a
        failure of the call. An offered result is a NEW offer id to add to a
        trip; the submitted offer is left as it was. Jinko enables Best Price
        Guarantee per account: a key it is not enabled for is answered HTTP 200
        `status: declined` with `decline.reason: feature_disabled`."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BestPriceGuaranteeRequest"
      responses:
        "200":
          description: The state of the request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BestPriceGuaranteeResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/best_price_guarantee/{id}:
    get:
      tags:
        - Hotels
      summary: "Best Price Guarantee: read the result of a request"
      description: "Read a request submitted with `POST /v1/best_price_guarantee`. The
        answer carries the state of the request in `status`: `pending` while the
        review runs, then `offered` with the new offer, or `declined` with the
        reason. A decline is a 200: it is an answer, not a failure of the call.
        A request of another key's tenant is answered 404, the same as one that
        does not exist."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: ngo_mfrggzdfmztwq2lknnwg23tpob
          required: true
          name: id
          in: path
        - schema:
            type: integer
            nullable: true
            minimum: 0
            maximum: 20
            description: How long this call waits for a request that is still pending, 0–20
              seconds (default 0).
            example: 15
          required: false
          name: wait_seconds
          in: query
      responses:
        "200":
          description: The state of the request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BestPriceGuaranteeResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/car_search:
    post:
      tags:
        - Cars
      summary: Search live car rental offers
      description: Search live car rental availability. `pick_up` names exactly one of
        an `airport_code` (IATA), a free-text `place` (resolved server-side —
        ambiguous text returns `candidates` to retry with), or `geo` coordinates
        (round-trip only). Date-times are branch-local `YYYY-MM-DDTHH:MM:SS`
        with no timezone. Omit `drop_off` to return the car to the pick-up
        branch, setting `drop_off_date_time`. Pass each offer's
        `trip_item_token` verbatim to `POST /v1/trip` as
        `add_item.trip_item_token` to add the rental to a trip, then check out
        as normal. `price.pay_now` is the only amount Jinko charges —
        `due_at_desk` is collected by the rental desk locally.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CarSearchRequest"
      responses:
        "200":
          description: Bookable car rental offers
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CarSearchResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: The request failed validation, or the rental supplier declined the
            search. When a supplier declined the request, `error.message` is
            “The rental request was declined. Try another vehicle, location or
            time.” **`BAD_REQUEST`** — The request was malformed or failed
            validation. Fix the request as the message describes; retrying it
            unchanged cannot succeed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: The rental request was declined. Try another vehicle, location or time.
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/car_cancel_preview:
    post:
      tags:
        - Cars
      summary: Preview the cost of cancelling a car rental booking
      description: "Quote what cancelling would cost right now: the fee in force and
        the refund it would leave. Nothing is cancelled. `fee_known: false`
        means the fee could not be established — render it as \"we will confirm
        the fee\", never as free cancellation. The returned `quote_id` is
        required by car_cancel_commit, and binds until `expires_at` where one is
        given. `cancellable: false` with `manual_required: true` means the
        cancellation cannot be completed online (fee unknown, rental changed
        after payment, fee in another currency or above the rental) and
        `refund_review_reason` says why: it is not a dead end — once the
        customer agrees, commit it with `manual_ok: true` and a Jinko agent
        completes it. `cancellable: false` without that flag is a rental that
        cannot be cancelled at all (already cancelled, or over), carrying the
        cancellation that stands where there is one. Guest-authenticated:
        booking_ref + last_name; a wrong pair returns 404 rather than confirming
        the booking's existence."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CarCancelPreviewRequest"
      responses:
        "200":
          description: Cancellation quote
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CarCancelPreviewResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking_ref + last_name pair.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "An exchange or another cancellation is already in flight for this
            rental, so no quote can be given: `code` is
            `active_operation_exists`, as a sibling of `error`, and
            `active_operation` names the cancellation running where it is one.
            Wait for it to finish (car_cancel_status) and preview again. A 409
            with no `code` beside `error` is not this case — the reference
            matched more than one booking."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/CarServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: an exchange is in progress for this rental; wait for it to finish
                    before cancelling
                code: active_operation_exists
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/car_cancel_commit:
    post:
      tags:
        - Cars
      summary: Cancel a car rental booking
      description: "Cancel the booking at the rental provider and refund the
        customer's payment minus the cancellation fee. Requires the
        `cancellation_id` from a preceding preview, binding the commit to the
        fee the customer saw. Safe to call twice — a committed cancellation is
        reported as it stands rather than repeated. `state: confirmed` is done;
        `state: pending` is recorded but not finished — the platform is still
        completing it, or a Jinko agent has it — so read car_cancel_status
        rather than committing again. `refund_pending_review: true` means the
        refund needs a person before it is issued. A preview that answered
        `manual_required: true` is committed with `manual_ok: true`, once the
        customer agrees: the cancellation is then recorded for a Jinko agent
        (`state: pending`, `refund_pending_review: true`) and nothing is sent to
        the rental company by this call. Without the flag that commit is refused
        409 `manual_required`. The other 409 refusals are `QUOTE_EXPIRED`
        (preview again), `quote_drift` (the refund moved; commit against the
        `retry_quote_id` it names after showing the customer `current.refund`),
        `active_operation_exists`, `not_cancellable` and `funds_unavailable` —
        see `CarServicingConflictCode`. In every one of them nothing was
        cancelled."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CarCancelCommitRequest"
      responses:
        "200":
          description: Cancellation result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CarCancelCommitResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking_ref + last_name pair.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "The commit cannot run as quoted; nothing was cancelled and no
            money moved. `code` says which case, as a sibling of `error` — see
            `CarServicingConflictCode` for the closed list and what each one
            asks of you. A 409 whose `code` is outside that list is NOT a
            servicing refusal: it arrives as the plain error envelope, with no
            `code` beside it."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/CarServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: this quote cannot be committed
                code: manual_required
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/car_cancel_status:
    post:
      tags:
        - Cars
      summary: Check the status of a car rental cancellation
      description: Report the latest cancellation attempt for the booking, whatever
        state it reached — including `refund_pending_review`, where the booking
        is cancelled but the refund awaits a human. Read-only. A 404 means
        either an unknown booking_ref + last_name pair or that no cancellation
        attempt exists yet for this booking — run car_cancel_preview first.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CarCancelStatusRequest"
      responses:
        "200":
          description: Latest cancellation state
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CarCancelStatusResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking_ref + last_name pair, or no cancellation attempt
            exists yet for this booking.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: Several booked car items match. Select a booked_item_id from items
            and repeat with booking_ref and booked_item_id.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/destination:
    get:
      tags:
        - Demand
      summary: Rank the top destinations by travel demand
      description: Ranks destinations by current demand share (a point-in-time
        snapshot). Optional `destination_country` (a `Country:<code>` selector,
        allowed only with `level=city`) narrows the ranking to that country’s
        destination cities.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: Origin selector `<Level>:<Code>` (e.g. `Country:US`), or `global`
              for all origins. Required for the destination endpoints.
            example: Country:US
          required: false
          name: origin
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: &a43
              - Solo
              - Couple
              - Group
              - Family
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: &a44
              - oneway
              - roundtrip
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Minimum trip length in nights (return_date − dep_date). Round-trips
              only.
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum trip length in nights (must be >= trip_duration_min).
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: "Minimum advance-purchase window in days (dep_date − search_date):
              keep demand from searches made at least this many days before
              departure."
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum advance-purchase window in days (must be >=
              search_window_min).
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            maximum: 90
            description: Number of most-recent days of search activity aggregated into the
              demand level (min 2, default 7, max 90 — a 1-day window is the
              current day, whose data is incomplete; data is kept for 90 days).
            example: 30
          required: false
          name: snapshot_window_days
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 20
            description: Maximum number of result rows. Default 20, max 200.
            example: 20
          required: false
          name: limit
          in: query
        - schema:
            type: string
            enum: &a45
              - country
              - city
            description: "Ranked output granularity: country (default) or city. Applies to
              destination/market (not audience)."
            example: city
          required: false
          name: level
          in: query
        - schema:
            type: string
            description: "Destination country selector `Country:<code>` (e.g. `Country:FR`).
              Optional and allowed ONLY together with level=city: it scopes the
              ranked destinations to a single country so that country’s cities
              are ranked. Must be a country — a City selector is rejected."
            example: Country:FR
          required: false
          name: destination_country
          in: query
      responses:
        "200":
          description: Destination demand ranking
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DestinationResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/market:
    get:
      tags:
        - Demand
      summary: Rank origin markets feeding a destination
      description: Ranks origin markets by current demand share (a point-in-time
        snapshot). Requires `destination`. Optional `origin_country` (a
        `Country:<code>` selector, allowed only with `level=city`) narrows the
        ranking to that country’s origin cities.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            description: Destination selector `<Level>:<Code>`. Required for this endpoint.
            example: City:PAR
          required: true
          name: destination
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Minimum trip length in nights (return_date − dep_date). Round-trips
              only.
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum trip length in nights (must be >= trip_duration_min).
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: "Minimum advance-purchase window in days (dep_date − search_date):
              keep demand from searches made at least this many days before
              departure."
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum advance-purchase window in days (must be >=
              search_window_min).
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            maximum: 90
            description: Number of most-recent days of search activity aggregated into the
              demand level (min 2, default 7, max 90 — a 1-day window is the
              current day, whose data is incomplete; data is kept for 90 days).
            example: 30
          required: false
          name: snapshot_window_days
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 20
            description: Maximum number of result rows. Default 20, max 200.
            example: 20
          required: false
          name: limit
          in: query
        - schema:
            type: string
            enum: *a45
            description: "Ranked output granularity: country (default) or city. Applies to
              destination/market (not audience)."
            example: city
          required: false
          name: level
          in: query
        - schema:
            type: string
            description: "Origin country selector `Country:<code>` (e.g. `Country:US`).
              Optional and allowed ONLY together with level=city: it scopes the
              ranked origin markets to a single country so that country’s cities
              are ranked. Must be a country — a City selector is rejected."
            example: Country:US
          required: false
          name: origin_country
          in: query
      responses:
        "200":
          description: Market demand ranking
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MarketResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/audience:
    get:
      tags:
        - Demand
      summary: Rank traveler audiences for a destination
      description: Ranks traveler audiences by current demand share (a point-in-time
        snapshot). Requires `destination`.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: Origin selector `<Level>:<Code>` (e.g. `Country:US`), or `global`
              for all origins. Required for the destination endpoints.
            example: Country:US
          required: false
          name: origin
          in: query
        - schema:
            type: string
            minLength: 1
            description: Destination selector `<Level>:<Code>`. Required for this endpoint.
            example: City:PAR
          required: true
          name: destination
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter (all
              departure dates).
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Minimum trip length in nights (return_date − dep_date). Round-trips
              only.
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum trip length in nights (must be >= trip_duration_min).
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: "Minimum advance-purchase window in days (dep_date − search_date):
              keep demand from searches made at least this many days before
              departure."
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            description: Maximum advance-purchase window in days (must be >=
              search_window_min).
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            maximum: 90
            description: Number of most-recent days of search activity aggregated into the
              demand level (min 2, default 7, max 90 — a 1-day window is the
              current day, whose data is incomplete; data is kept for 90 days).
            example: 30
          required: false
          name: snapshot_window_days
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 20
            description: Maximum number of result rows. Default 20, max 200.
            example: 20
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: Audience demand ranking
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudienceResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/trend:
    get:
      tags:
        - Demand
      summary: Demand time series for explicit origin/destination pairs
      description: "Deep dive: returns one de-sampled search-volume series per
        (origin, destination) pair. v1 allows a list on only one side (a single
        origin OR a single destination)."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            description: "Comma-separated origin selectors `<Level>:<Code>` (e.g.
              `Country:US,Country:CA`). v1: at most one of origins/destinations
              may have more than one entry."
            example: Country:US
          required: true
          name: origins
          in: query
        - schema:
            type: string
            minLength: 1
            description: Comma-separated destination selectors `<Level>:<Code>` (e.g.
              `Country:FR`).
            example: Country:FR,Country:DE,Country:GB
          required: true
          name: destinations
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both (recommended) for no departure-date
              filter — each bucket then counts searches for all departure dates.
              A window anchored at the query date counts only
              long-advance-purchase searches in old buckets and near-departure
              searches in recent ones, ramping the curve artificially.
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter.
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            description: "Number of buckets N, in the chosen granularity unit (min 2; max
              depends on granularity: day <= 60, week <= 52, month <= 12;
              default 12). The series spans the last N complete buckets,
              excluding the in-progress one (day: last N days ending yesterday;
              week: last N full Monday-Sunday weeks; month: last N full calendar
              months)."
            example: 12
          required: false
          name: trend_window
          in: query
        - schema:
            type: string
            enum: &a46
              - day
              - week
              - month
            description: "Bucket size for the returned series: week (default), day, or
              month."
            example: week
          required: false
          name: granularity
          in: query
      responses:
        "200":
          description: Per-pair demand time series
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrendResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/destination/trend:
    get:
      tags:
        - Demand
      summary: Demand time series for the top-N destinations
      description: Ranks destinations reachable from origin by within-window growth,
        then returns each top-N destination’s series. Optional
        `destination_country` (a `Country:<code>` selector, allowed only with
        `level=city`) narrows the ranking to that country’s destination cities.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: Origin selector `<Level>:<Code>` (e.g. `Country:US`), or `global`
              for all origins. Required for the destination endpoints.
            example: Country:US
          required: false
          name: origin
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both (recommended) for no departure-date
              filter — each bucket then counts searches for all departure dates.
              A window anchored at the query date counts only
              long-advance-purchase searches in old buckets and near-departure
              searches in recent ones, ramping the curve artificially.
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter.
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            description: "Number of buckets N, in the chosen granularity unit (min 2; max
              depends on granularity: day <= 60, week <= 52, month <= 12;
              default 12). The series spans the last N complete buckets,
              excluding the in-progress one (day: last N days ending yesterday;
              week: last N full Monday-Sunday weeks; month: last N full calendar
              months)."
            example: 12
          required: false
          name: trend_window
          in: query
        - schema:
            type: string
            enum: *a46
            description: "Bucket size for the returned series: week (default), day, or
              month."
            example: week
          required: false
          name: granularity
          in: query
        - schema:
            type: string
            enum: *a45
            description: "Ranked output granularity: country (default) or city. Applies to
              destination/market (not audience)."
            example: city
          required: false
          name: level
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 10
            description: Maximum number of series (top-N keys). Default 10, max 50.
            example: 10
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Destination country selector `Country:<code>` (e.g. `Country:FR`).
              Optional and allowed ONLY together with level=city: it scopes the
              ranked destinations to a single country so that country’s cities
              are ranked. Must be a country — a City selector is rejected."
            example: Country:FR
          required: false
          name: destination_country
          in: query
      responses:
        "200":
          description: Top-N destination time series
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrendResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/market/trend:
    get:
      tags:
        - Demand
      summary: Demand time series for the top-N source markets
      description: Ranks source markets feeding the destination by within-window
        growth, then returns each top-N market’s series. Requires `destination`.
        Optional `origin_country` (a `Country:<code>` selector, allowed only
        with `level=city`) narrows the ranking to that country’s origin cities.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            description: Destination selector `<Level>:<Code>`. Required for this endpoint.
            example: City:PAR
          required: true
          name: destination
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both (recommended) for no departure-date
              filter — each bucket then counts searches for all departure dates.
              A window anchored at the query date counts only
              long-advance-purchase searches in old buckets and near-departure
              searches in recent ones, ramping the curve artificially.
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter.
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            description: "Number of buckets N, in the chosen granularity unit (min 2; max
              depends on granularity: day <= 60, week <= 52, month <= 12;
              default 12). The series spans the last N complete buckets,
              excluding the in-progress one (day: last N days ending yesterday;
              week: last N full Monday-Sunday weeks; month: last N full calendar
              months)."
            example: 12
          required: false
          name: trend_window
          in: query
        - schema:
            type: string
            enum: *a46
            description: "Bucket size for the returned series: week (default), day, or
              month."
            example: week
          required: false
          name: granularity
          in: query
        - schema:
            type: string
            enum: *a45
            description: "Ranked output granularity: country (default) or city. Applies to
              destination/market (not audience)."
            example: city
          required: false
          name: level
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 10
            description: Maximum number of series (top-N keys). Default 10, max 50.
            example: 10
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Origin country selector `Country:<code>` (e.g. `Country:US`).
              Optional and allowed ONLY together with level=city: it scopes the
              ranked origin markets to a single country so that country’s cities
              are ranked. Must be a country — a City selector is rejected."
            example: Country:US
          required: false
          name: origin_country
          in: query
      responses:
        "200":
          description: Top-N market time series
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrendResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/audience/trend:
    get:
      tags:
        - Demand
      summary: Demand time series per traveler-type segment
      description: Returns a series for each traveler-type segment (excluding Unknown)
        for the given destination. Requires `destination`.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            description: Origin selector `<Level>:<Code>` (e.g. `Country:US`), or `global`
              for all origins. Required for the destination endpoints.
            example: Country:US
          required: false
          name: origin
          in: query
        - schema:
            type: string
            minLength: 1
            description: Destination selector `<Level>:<Code>`. Required for this endpoint.
            example: City:PAR
          required: true
          name: destination
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: Start of the departure window (YYYY-MM-DD). Supply together with
              departure_date_to; omit both (recommended) for no departure-date
              filter — each bucket then counts searches for all departure dates.
              A window anchored at the query date counts only
              long-advance-purchase searches in old buckets and near-departure
              searches in recent ones, ramping the curve artificially.
            example: "2026-07-01"
          required: false
          name: departure_date_from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            description: End of the departure window (YYYY-MM-DD). Supply together with
              departure_date_from; omit both for no departure-date filter.
            example: "2026-07-31"
          required: false
          name: departure_date_to
          in: query
        - schema:
            type: string
            enum: *a43
            example: Couple
          required: false
          name: traveler_type
          in: query
        - schema:
            type: string
            enum: *a44
            example: roundtrip
          required: false
          name: trip_type
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 5
          required: false
          name: trip_duration_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 9
          required: false
          name: trip_duration_max
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 7
          required: false
          name: search_window_min
          in: query
        - schema:
            type: integer
            nullable: true
            minimum: 0
            example: 30
          required: false
          name: search_window_max
          in: query
        - schema:
            type: integer
            minimum: 2
            description: "Number of buckets N, in the chosen granularity unit (min 2; max
              depends on granularity: day <= 60, week <= 52, month <= 12;
              default 12). The series spans the last N complete buckets,
              excluding the in-progress one (day: last N days ending yesterday;
              week: last N full Monday-Sunday weeks; month: last N full calendar
              months)."
            example: 12
          required: false
          name: trend_window
          in: query
        - schema:
            type: string
            enum: *a46
            description: "Bucket size for the returned series: week (default), day, or
              month."
            example: week
          required: false
          name: granularity
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 10
            description: Maximum number of series (top-N keys). Default 10, max 50.
            example: 10
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: Per-segment time series
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrendResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/get_booking:
    post:
      tags:
        - Post-booking
      summary: Retrieve booked item IDs and per-item servicing eligibility using the
        Jinko booking reference
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GetBookingRequest"
      responses:
        "200":
          description: Retrieve booked item IDs and per-item servicing eligibility using
            the Jinko booking reference
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetBookingResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: Choose booked_item_id when several booked items match; other
            conflicts report the current resource state.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/refund_check:
    post:
      tags:
        - Post-booking
      summary: DEPRECATED — use /v1/flight_refund_preview. Check refund eligibility
        only; use flight_refund_preview for customer-facing amounts
      deprecated: true
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefundCheckRequest"
      responses:
        "200":
          description: Check refund eligibility only; use flight_refund_preview for
            customer-facing amounts
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RefundCheckResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "Servicing refusal or booking item selection required. A booking
            returned by get_booking with status failed (for example, after
            payment), expired_quote, pending or exchange_partial_failure is
            refused with `code: not_cancellable`, `reason_code:
            booking_not_active` and a platform sentence in `error.message`, when
            the caller may service the booking. Any other caller gets the same
            404 as for an unknown booking."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/FlightServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/refund_commit:
    post:
      tags:
        - Post-booking
      summary: DEPRECATED — use /v1/flight_refund_commit. Initiate a refund for a
        booked flight
      deprecated: true
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefundCommitRequest"
      responses:
        "200":
          description: Initiate a refund for a booked flight
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RefundCommitResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "Servicing refusal or booking item selection required. A booking
            returned by get_booking with status failed (for example, after
            payment), expired_quote, pending or exchange_partial_failure is
            refused with `code: not_cancellable`, `reason_code:
            booking_not_active` and a platform sentence in `error.message`, when
            the caller may service the booking. Any other caller gets the same
            404 as for an unknown booking."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/FlightServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/refund_status:
    post:
      tags:
        - Post-booking
      summary: DEPRECATED — use /v1/flight_refund_status. Check the status of a refund
      deprecated: true
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefundStatusRequest"
      responses:
        "200":
          description: Check the status of a refund
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RefundStatusResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: No refund exists for this booking, or the booking itself could not
            be read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: no refund found for this booking
        "409":
          description: Choose booked_item_id when several booked items match; other
            conflicts report the current resource state.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/exchange_shop:
    post:
      tags:
        - Post-booking
      summary: Shop for flight exchange alternatives
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExchangeShopRequest"
      responses:
        "200":
          description: Shop for flight exchange alternatives
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExchangeShopResponse"
        "400":
          description: A leg selection the booked itinerary or the supplier refuses. When
            the booked itinerary refuses it, the message lists the booked legs;
            when the supplier refuses it, the message is “This exchange cannot
            be processed as requested. Change the selected flights or contact
            Jinko support.” **`INVALID_SEGMENTS_TO_EXCHANGE`** — An exchange
            selection does not match a booked leg. Read the booking and select
            each leg by its booked origin and destination.
            **`PARTIAL_EXCHANGE_UNSUPPORTED`** — The supplier cannot keep
            unselected legs unchanged for this booking. Name every booked leg in
            segments_to_exchange to reshop the whole itinerary.
            **`LEG_ALREADY_DEPARTED`** — An exchange names a booked leg whose
            first flight has already departed. Change only legs that have not
            departed; the message lists the booked legs.
            **`DEPARTURE_DATE_IN_PAST`** — An exchange asks for a departure date
            before today at the departure airport. Choose a departure date from
            today onwards, in the departure airport’s local time.
            **`LEG_DATES_OUT_OF_ORDER`** — The new dates would put the legs of
            the itinerary out of order. Pick dates that keep each leg after the
            one before it, or change both legs in one request; the message lists
            the booked legs. **`INVALID_EXCHANGE_REQUEST`** — The supplier
            refused the exchange request itself. Change the selected flights, or
            contact Jinko support. The refusal does not say which part of the
            request was refused.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "Choose booked_item_id when several booked items match
            (item_selection_required). Otherwise the booking cannot be exchanged
            as it stands. **`NOT_EXCHANGEABLE`** — The booking cannot be
            exchanged as it stands: no ticket or flight is left to change, or
            the fare does not permit the change. Do not retry the same exchange.
            Contact Jinko support if the customer still needs a change."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/exchange_price:
    post:
      tags:
        - Post-booking
      summary: Price a specific exchange offer
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExchangePriceRequest"
      responses:
        "200":
          description: Price a specific exchange offer
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExchangePriceResponse"
        "400":
          description: The supplier refused the request itself (an expired or malformed
            offer, a leg selection it cannot serve), with the message “This
            exchange cannot be processed as requested. Change the selected
            flights or contact Jinko support.” Nothing was priced; shop again.
            **`INVALID_EXCHANGE_REQUEST`** — The supplier refused the exchange
            request itself. Change the selected flights, or contact Jinko
            support. The refusal does not say which part of the request was
            refused. **`INVALID_SEGMENTS_TO_EXCHANGE`** — An exchange selection
            does not match a booked leg. Read the booking and select each leg by
            its booked origin and destination.
            **`PARTIAL_EXCHANGE_UNSUPPORTED`** — The supplier cannot keep
            unselected legs unchanged for this booking. Name every booked leg in
            segments_to_exchange to reshop the whole itinerary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "The exchange cannot be carried out automatically, so no price is
            given; nothing was exchanged or charged. `code` says why, as a
            sibling of `error` — see `ExchangePriceConflictCode` — and
            `error.message` states it in figures where there are any. For
            `funds_unavailable`, `multi_currency_basis` and `manual_required`,
            committing the same offer sends the request to Jinko support, who
            will complete it and refund the customer; `not_exchangeable` is not
            sent to support. Choose `item_id` when several booked items match. A
            409 whose `code` is outside that list is not one of these refusals:
            it arrives as the plain error envelope."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ExchangePriceConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
                  - $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: this exchange would refund 1050.00 USD, and only 789.00 is still
                    refundable on the original payment. It can't be refunded
                    automatically. Confirming this exchange sends it to Jinko
                    support, who will complete it and refund you.
                code: funds_unavailable
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/exchange_commit:
    post:
      tags:
        - Post-booking
      summary: Commit a flight exchange
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExchangeCommitRequest"
      responses:
        "200":
          description: Commit a flight exchange
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExchangeCommitResponse"
        "400":
          description: The supplier refused the request when the commit priced the offer
            again (an expired or malformed offer, a leg selection it cannot
            serve), with the message “This exchange cannot be processed as
            requested. Change the selected flights or contact Jinko support.”
            Nothing was exchanged or charged; shop again.
            **`INVALID_EXCHANGE_REQUEST`** — The supplier refused the exchange
            request itself. Change the selected flights, or contact Jinko
            support. The refusal does not say which part of the request was
            refused. **`INVALID_SEGMENTS_TO_EXCHANGE`** — An exchange selection
            does not match a booked leg. Read the booking and select each leg by
            its booked origin and destination.
            **`PARTIAL_EXCHANGE_UNSUPPORTED`** — The supplier cannot keep
            unselected legs unchanged for this booking. Name every booked leg in
            segments_to_exchange to reshop the whole itinerary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "Nothing was exchanged or charged by this call. `code` says why —
            see `ExchangeCommitConflictCode`. On `funds_unavailable`,
            `multi_currency_basis` and `manual_required` the exchange can't be
            refunded automatically, so the request has been sent to Jinko
            support, who will complete it and refund the customer; follow it on
            `get_booking` at `items[].servicing.exchange`. On
            `exchange_in_progress` an exchange for this booking is already
            waiting for payment or running: call exchange_status for its
            progress and its `checkout_url`. On `not_exchangeable` the booking
            cannot be exchanged as it stands (no ticket or flight left to
            change, or a fare that does not permit it); nothing is sent to
            support. Choose `item_id` when several booked items match. A 409
            whose `code` is outside that list arrives as the plain error
            envelope."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ExchangeCommitConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
                  - $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: This exchange can't be refunded automatically, so it has been sent to
                    Jinko support. They will complete it and refund you; there
                    is nothing else to do.
                code: funds_unavailable
                manual_handling:
                  status: pending
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/exchange_status:
    post:
      tags:
        - Post-booking
      summary: Check the status of an exchange
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExchangeStatusRequest"
      responses:
        "200":
          description: Check the status of an exchange
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExchangeStatusResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: Choose booked_item_id when several booked items match; other
            conflicts report the current resource state.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_cancel:
    post:
      tags:
        - Post-booking
      summary: "DEPRECATED — use /v1/hotel_cancel_preview and /v1/hotel_cancel_commit.
        Cancel a hotel booking and get a refund when eligible. Preview and
        commit in one call — POST /v1/hotel_cancel_preview plus
        /v1/hotel_cancel_commit is the two-step form, which shows the customer
        the refund before anything is cancelled. `refund_amount` is what the
        CUSTOMER gets back; all amounts are customer-facing only. Returning the
        money outlives this call: poll the `operation` handle with POST
        /v1/hotel_cancel_status. Every call here needs API authentication (an
        API key or a Bearer token); this is about which mode identifies the
        booking. Call get_booking first, then send booking_ref and the selected
        booked_item_id. Guests must send last_name; an owning credential may
        omit it. The deprecated `provider`, `order_id`, `provider_reference` and
        `provider_booking_id` are accepted until 2027-04-30 where the request
        declares them; a request that sends one is answered with `Deprecation`
        and `Sunset` headers."
      deprecated: true
      description: Call get_booking first. Use booking_ref and the selected
        booked_item_id for every servicing action. last_name is required for
        guest lookup; an owning credential may omit it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers. A
        409 item_selection_required returns safe items to choose from.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelCancelRequest"
      responses:
        "200":
          description: "Cancel a hotel booking and get a refund when eligible. Preview and
            commit in one call — POST /v1/hotel_cancel_preview plus
            /v1/hotel_cancel_commit is the two-step form, which shows the
            customer the refund before anything is cancelled. `refund_amount` is
            what the CUSTOMER gets back; all amounts are customer-facing only.
            Returning the money outlives this call: poll the `operation` handle
            with POST /v1/hotel_cancel_status. Every call here needs API
            authentication (an API key or a Bearer token); this is about which
            mode identifies the booking. Call get_booking first, then send
            booking_ref and the selected booked_item_id. Guests must send
            last_name; an owning credential may omit it. The deprecated
            `provider`, `order_id`, `provider_reference` and
            `provider_booking_id` are accepted until 2027-04-30 where the
            request declares them; a request that sends one is answered with
            `Deprecation` and `Sunset` headers."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelCancelResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: Choose booked_item_id when several booked items match; other
            conflicts report the current resource state.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_cancel_preview:
    post:
      tags:
        - Post-booking
      summary: Preview what cancelling a hotel booking would cost
      description: "Quote what cancelling would return to the customer right now: the
        refund, the penalty in force, and the policy behind them. NOTHING is
        cancelled. `refund` is the customer figure — what they paid for the item
        less the penalty. All amounts are customer-facing only. `commitable:
        false` means a commit would be refused and `not_commitable_reason` says
        why. The handle this returns is named `quote`: it is what POST
        /v1/hotel_cancel_commit consumes, and it stops binding at `expires_at`.
        Every call here needs API authentication; this is about which mode
        identifies the booking. Call get_booking first, then send booking_ref
        and the selected booked_item_id. An owning credential identifies the
        booking without last_name; guests must supply it. The deprecated
        `provider`, `order_id`, `provider_reference` and `provider_booking_id`
        are accepted until 2027-04-30 where the request declares them; a request
        that sends one is answered with `Deprecation` and `Sunset` headers."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelCancelPreviewRequest"
      responses:
        "200":
          description: What cancelling would cost
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelCancelPreviewResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "The supplier will not cancel this booking as it stands — it is
            already cancelled, or was never confirmed. A hotel booking that is
            no longer active is also refused with `reason_code:
            booking_not_active` when the caller may service it (any other caller
            gets the same 404 as for an unknown booking). `code` is
            `not_cancellable`, as a sibling of `error`. `error.message` is “This
            booking cannot be cancelled online. Contact Jinko support.” when the
            supplier refused, or the platform’s sentence when the booking is no
            longer active. There is no quote to show and nothing to commit.
            Another operation already in flight on the item (an exchange, a
            refund or a cancellation) is refused the same way, with `code:
            active_operation_exists` and `active_operation` naming it: follow it
            with the status route and preview again once it has finished. A 409
            with no `code` beside `error` is not this case — the reference
            matched more than one booking."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: This booking cannot be cancelled online. Contact Jinko support.
                code: not_cancellable
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_cancel_commit:
    post:
      tags:
        - Post-booking
      summary: Cancel a hotel booking against a quote the customer accepted
      description: "Start the cancellation the preview described. The body is the
        `quote` handle and the `acknowledged` figure PLUS the same booking_ref,
        item_id and last_name the preview took: ownership is re-checked here
        rather than carried by the handle, so they have to be sent again.
        `acknowledged` is the refund the customer was shown, copied from the
        preview as it arrived (`value` and `decimal_places` included): if your
        figure differs from the still-live quote’s refund, the call is refused
        with 409 `quote_drift`. `retry_quote_id` is that same quote’s handle and
        `current.refund` its figure. Show it to the customer, then commit again
        with that handle and figure. Nothing is cancelled. If the supplier’s
        policy moved since the quote, `quote_drift` has no `retry_quote_id`;
        preview again. The other refusals are 409 `QUOTE_EXPIRED` (run
        hotel_cancel_preview again), `active_operation_exists` (poll the
        `active_operation` when present instead of starting a second one),
        `not_cancellable` and `funds_unavailable`. Success does NOT mean the
        money has moved: cancelling at the supplier and refunding the customer
        are separate steps, so the answer is an `operation` handle to poll with
        POST /v1/hotel_cancel_status."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelCancelCommitRequest"
      responses:
        "200":
          description: The cancellation was accepted and is running
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelCancelCommitResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "The commit cannot run as quoted; nothing was cancelled. `code`
            says which case, as a sibling of `error` — see
            `ServicingConflictCode` for the closed list and what each one asks
            of you. A booking that is no longer active is refused with `code:
            not_cancellable`, `reason_code: booking_not_active` and a platform
            sentence in `error.message`, when the caller may service it. A 409
            whose `code` is outside that list is NOT a servicing refusal: it
            arrives as the plain error envelope, with no `code` beside it."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: Your acknowledged figure differs from the quote’s refund; nothing was
                    cancelled. Show the customer `current.refund`, then commit
                    again with `retry_quote_id` (the same quote handle) and that
                    figure.
                code: quote_drift
                requote: svq_01J8AB4N7GLY3Q0D
                current:
                  refund:
                    value: 20500
                    currency: USD
                    decimal_places: 2
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/hotel_cancel_status:
    post:
      tags:
        - Post-booking
      summary: Check how a hotel cancellation ended
      description: Report where one cancellation has got to, named by the `operation`
        handle a commit (or POST /v1/hotel_cancel) returned. Read-only. `state`
        is the platform view — keep polling while it is `in_progress` or
        `attention_required`, both of which mean the operation is still alive.
        `provider` is what the supplier says about the booking and `money` is
        where the refund itself has got to; the two move independently, so a
        booking can read `cancelled` while the money is still in flight. Do not
        tell a customer they have been refunded until `money.vehicle_state` says
        `paid`. Same auth modes as hotel_cancel_preview.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HotelCancelStatusRequest"
      responses:
        "200":
          description: Where the cancellation has got to
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelCancelStatusResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown operation or booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: Several booked items match. Select a booked_item_id from items and
            repeat with booking_ref and booked_item_id.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_refund_preview:
    post:
      tags:
        - Post-booking
      summary: Preview what cancelling a booked flight (every ticket on the item)
        would return to the customer
      description: "Quote what the customer would get back for this flight item, every
        ticket on it, right now: the refund, the penalty in force, and every
        document the operation would cover. NOTHING is sent to the airline.
        `refund` is what the customer paid less the penalty. All amounts are
        customer-facing only. The platform decides WHICH operation this is and
        reports it as `operation_kind`: a ticket still inside its void window is
        `void` — the entire charge is reversed, penalty-free — and anything else
        is `cancel`, a refund under the fare rules. You cannot ask for one; read
        what you are given, because the void window closes with time.
        `commitable: false` with `support_level: MANUAL_REQUIRED` is not a dead
        end: the commit takes `manual_ok: true` and hands the operation to a
        Jinko agent. The handle this returns is named `quote`: it is what POST
        /v1/flight_refund_commit consumes, and it stops binding at `expires_at`.
        Every call here needs API authentication; this is about which mode
        identifies the booking. Call get_booking first, then send booking_ref
        and the selected booked_item_id. Guests must send last_name; owning
        credentials may omit it. The deprecated `provider`, `order_id`,
        `provider_reference` and `provider_booking_id` are accepted until
        2027-04-30 where the request declares them; a request that sends one is
        answered with `Deprecation` and `Sunset` headers."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightRefundPreviewRequest"
      responses:
        "200":
          description: What cancelling the flight item would return
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightRefundPreviewResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "The airline will not refund this item as it stands — a
            non-refundable fare, or every document already voided or refunded. A
            booking that is no longer active is also refused with `reason_code:
            booking_not_active` when the caller may service it (any other caller
            gets the same 404 as for an unknown booking). `code` is
            `not_cancellable`, as a sibling of `error`. `error.message` is “This
            booking cannot be cancelled online. Contact Jinko support.” when the
            airline refused, or the platform’s sentence when the booking is no
            longer active. There is no quote to show, nothing to commit, and
            `manual_ok` does not apply. Another operation already in flight on
            the item (an exchange, a refund or a cancellation) is refused the
            same way, with `code: active_operation_exists` and
            `active_operation` naming it: follow it with the status route and
            preview again once it has finished. A manual request no Jinko agent
            has picked up yet does not block a preview. A 409 with no `code`
            beside `error` is not this case — the reference matched more than
            one booking, or the booking holds several flights and `item_id`
            named none."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/FlightServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: This booking cannot be cancelled online. Contact Jinko support.
                code: not_cancellable
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_refund_commit:
    post:
      tags:
        - Post-booking
      summary: Refund or void a booked flight (every ticket on the item) against a
        quote the customer accepted
      description: "Start the operation the preview described — a refund, or a void of
        the original charge, whichever the preview reported as `operation_kind`.
        The body is the `quote` handle and the `acknowledged` figure PLUS the
        same auth mode the preview took: ownership is re-checked here rather
        than carried by the handle, so the mode has to be sent again.
        `acknowledged` is the refund the customer was shown, copied from the
        preview as it arrived (`value` and `decimal_places` included): if your
        figure differs from the still-live quote’s refund, the call is refused
        with 409 `quote_drift`. `retry_quote_id` is that same quote’s handle and
        `current.refund` its figure. Show it to the customer, then commit again
        with that handle and figure. Nothing is sent to the airline. A
        MANUAL_REQUIRED quote needs `manual_ok: true`: the operation is then
        raised for a Jinko agent and answers `attention_required` with `reason:
        manual_required`, again without the airline being called. Committing one
        without the flag is refused 409 `manual_required`. That submission is
        also the one case where `acknowledged` may be left out: a
        MANUAL_REQUIRED quote whose penalty is unknown carries no `refund` to
        acknowledge, and there is nothing to compare against. Whenever the
        preview DID name a refund, send it. The other refusals are 409
        `QUOTE_EXPIRED` (preview again), `active_operation_exists` (poll the
        `active_operation` when present instead of starting a second one),
        `not_cancellable`, `funds_unavailable`, `superseded`, and — when the
        preview already said `commitable: false` and you committed anyway — that
        quote’s own reason answered back as the code: `penalty_exceeds_sell` or
        `multi_currency_basis`. Success does NOT mean the money has moved:
        giving the tickets back at the airline and returning the money to the
        customer are separate steps, so the answer is an `operation` handle to
        poll with POST /v1/flight_refund_status."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightRefundCommitRequest"
      responses:
        "200":
          description: The refund or void was accepted and is running
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightRefundCommitResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: "The commit cannot run as quoted; nothing was sent to the airline.
            `code` says which case, as a sibling of `error` — see
            `FlightServicingConflictCode` for the closed list and what each one
            asks of you. A booking that is no longer active is refused with
            `code: not_cancellable`, `reason_code: booking_not_active` and a
            platform sentence in `error.message`, when the caller may service
            it. A 409 whose `code` is outside that list is NOT a servicing
            refusal: it arrives as the plain error envelope, with no `code`
            beside it."
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/FlightServicingConflictResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
              example:
                error:
                  code: CONFLICT
                  message: "This refund cannot be carried out automatically and nothing was sent
                    to the airline. The quote said `support_level:
                    MANUAL_REQUIRED`; commit again with `manual_ok: true` to
                    hand it to a Jinko agent, then poll the operation."
                code: manual_required
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/flight_refund_status:
    post:
      tags:
        - Post-booking
      summary: Check how a flight refund or void ended
      description: Report where one refund or void has got to, named by the
        `operation` handle a commit (or POST /v1/refund_commit) returned.
        Read-only. `state` is the platform view — keep polling while it is
        `in_progress` or `attention_required`, both of which mean the operation
        is still alive; `attention_required` means a Jinko agent has it, and
        `park_deadline` says how long that lasts. `operation_kind` says which
        operation actually ran. `provider` is what the airline says, including
        what became of each ticket and EMD — an operation has done its work when
        every document it covers has reached a terminal state. `money` is where
        the refund itself has got to; the two move independently, so the tickets
        can read refunded while the money is still in flight. Do not tell a
        customer they have been refunded until `money.vehicle_state` says
        `paid`. Same auth modes as flight_refund_preview.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FlightRefundStatusRequest"
      responses:
        "200":
          description: Where the refund or void has got to
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FlightRefundStatusResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Unknown operation or booking, or one this credential may not read.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: booking not found
        "409":
          description: Several booked items match. Select a booked_item_id from items and
            repeat with booking_ref and booked_item_id.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: "#/components/schemas/ErrorResponse"
                  - $ref: "#/components/schemas/BookingSelectionConflict"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/webhooks:
    post:
      tags:
        - Webhooks
      summary: Register a webhook endpoint for booking lifecycle events
      description: 'Subscribe a callback URL to `booking.processing`,
        `booking.completed`, `booking.failed`, `booking.partial`,
        `servicing.completed`, `servicing.exchange_confirmed`,
        `servicing.ticket_issued`, or `servicing.failed`. The response includes
        the HMAC signing secret ONCE. Deliveries are signed with
        `X-Jinko-Signature: sha256=<hex>` over `"<X-Jinko-Timestamp>.<raw
        body>"`.'
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWebhookRequest"
      responses:
        "201":
          description: Webhook registered (secret shown once)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookCreatedResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
    get:
      tags:
        - Webhooks
      summary: List the caller's webhook subscriptions
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      responses:
        "200":
          description: Webhook subscriptions (secret masked)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookListResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/webhooks/{id}:
    get:
      tags:
        - Webhooks
      summary: Get a webhook subscription and its recent deliveries
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: "42"
          required: true
          name: id
          in: path
      responses:
        "200":
          description: Webhook subscription + recent deliveries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDetailResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
    delete:
      tags:
        - Webhooks
      summary: Delete a webhook subscription
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: "42"
          required: true
          name: id
          in: path
      responses:
        "200":
          description: Webhook deleted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeleteResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/webhooks/{id}/test:
    post:
      tags:
        - Webhooks
      summary: Send a sample signed event to validate the endpoint
      description: "Delivers a `livemode: false` sample event so you can verify
        signature + connectivity without a real booking."
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: "42"
          required: true
          name: id
          in: path
      responses:
        "202":
          description: Test event enqueued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookTestResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/webhooks/{id}/deliveries:
    get:
      tags:
        - Webhooks
      summary: List deliveries for a webhook subscription
      description: Lists event deliveries to a subscription you own, newest first.
        Each row records one event delivery and its attempts. `payload` is the
        exact envelope sent, or null after it is purged 30 days after the
        delivery's last attempt or replay. Use next_cursor to fetch the next
        page.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: "42"
          required: true
          name: id
          in: path
        - schema:
            type: integer
            minimum: 1
            maximum: 100
            description: Maximum rows to return. Defaults to 20 when omitted.
            example: 20
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: Opaque pagination cursor.
          required: false
          name: cursor
          in: query
        - schema:
            type: string
            enum:
              - pending
              - delivered
              - failed
              - exhausted
          required: false
          name: status
          in: query
        - schema:
            type: string
            example: booking.completed
          required: false
          name: event_type
          in: query
      responses:
        "200":
          description: Webhook deliveries, newest first
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeliveryListResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: The operation conflicts with the current state of the resource
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: CONFLICT
                  message: The operation conflicts with the current state of the resource.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
  /v1/webhooks/{id}/deliveries/{delivery_id}/replay:
    post:
      tags:
        - Webhooks
      summary: Replay a webhook delivery
      description: Replays a delivered or exhausted event delivery for a subscription
        you own. Sets its status to pending, resets attempt_count to 0,
        increments replay_count, and enqueues a fresh delivery of the same
        payload with a new signature timestamp. The replay keeps the same
        event_id, so your idempotency key still applies. Pending or failed
        deliveries are still being delivered or retried and cannot be replayed.
        Payloads are purged 30 days after the delivery's last attempt or replay;
        a delivery whose payload was purged can no longer be replayed.
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            example: "42"
          required: true
          name: id
          in: path
        - schema:
            type: string
            example: "981"
          required: true
          name: delivery_id
          in: path
      responses:
        "202":
          description: Webhook delivery replay enqueued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookReplayResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "401":
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/authentication/api-keys
        "402":
          description: Payment required — organization balance exhausted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYMENT_REQUIRED
                  message: Insufficient balance — this call costs $0.0150 and your organization
                    has $0.0000 available. Top up at
                    https://dashboard.gojinko.com/developers/billing/topup
                  doc_url: https://docs.gojinko.com/concepts/errors
        "404":
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "409":
          description: "CONFLICT: delivery_in_progress while delivery or retries are
            pending, or payload_purged once the payload is purged, 30 days after
            the delivery's last attempt or replay. The replay reason is in code
            beside error."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookReplayConflictResponse"
        "410":
          description: The resource this request names no longer exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: GONE
                  message: The resource no longer exists.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "422":
          description: Validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: BAD_REQUEST
                  message: A required field is missing or invalid.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "429":
          description: Rate limit or quota exceeded
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests. Retry after the Retry-After delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "502":
          description: The travel provider rejected the request, or an upstream call failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_REJECTED
                  message: The request was declined for this offer. Try another offer.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "503":
          description: No travel provider can serve the request right now
          headers:
            Retry-After:
              description: Seconds to wait before retrying, forwarded verbatim from the
                upstream service. Absent when the upstream named no interval.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_UNAVAILABLE
                  message: The service is temporarily unavailable. Retry after the Retry-After
                    delay.
                  doc_url: https://docs.gojinko.com/concepts/errors
        "504":
          description: The travel provider did not answer in time
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: UPSTREAM_TIMEOUT
                  message: The request timed out before a result was available. Retry the request.
                  doc_url: https://docs.gojinko.com/concepts/errors
