---
title: "Shop for flight exchange alternatives"
method: POST
path: "/v1/exchange_shop"
tags: ["Post-booking"]
---

# Shop for flight exchange alternatives

`POST /v1/exchange_shop`

## Request

- Base URL: `https://api.gojinko.com`
- URL: `https://api.gojinko.com/v1/exchange_shop`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

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.

## Request body

- ExchangeShopRequest
  - `booking_ref` string: Jinko booking reference. Call get_booking first, then select its booked_item_id for servicing.
  - `booked_item_id` string: 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.
  - `last_name` string: Required for guest lookup. A credential that owns the booking may omit it; ownership is checked by the platform.
  - `order_id` string: 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.
  - `provider` string: 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.
  - `intent` IntentInput
    - `user_intent` string, nullable: The user's natural-language intent: the Alpic PII-stripped paraphrase when available, else a best-effort fallback to the client-provided NL query.
  - `segments_to_exchange` ExchangeLegSelection[]: 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.
    - `origin_location` object, required
      - `code` string, required
      - `type` 'city' | 'airport', required
    - `destination_location` object, required
      - `code` string, required
      - `type` 'city' | 'airport', required
    - `departure_date` string, date, required: The new departure date for this booked leg (YYYY-MM-DD).
  - `preferred_departure_date` string: 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.

## Response `200`

Shop for flight exchange alternatives

- ExchangeShopResponse
  - `support_level` 'AUTO' | 'MANUAL_REQUIRED' | 'UNSUPPORTED': 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`.
  - `reason_code` string: 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.
  - `reason` string: 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`.
  - `offers` ExchangeOffer[]
    - `offer_id` string: The handle POST /v1/exchange_price and /v1/exchange_commit take.
    - `description` string
    - `estimated_payment_outcome` string: 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.
    - `estimated_amount` Money: 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.
      - `amount` number: 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).
      - `value` integer: 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.
      - `currency` string: ISO 4217 currency code.
      - `decimal_places` integer: 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.
      - `display` string: 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.
    - `non_refundable_amount` Money: 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.
      - `amount` number: 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).
      - `value` integer: 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.
      - `currency` string: ISO 4217 currency code.
      - `decimal_places` integer: 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.
      - `display` string: 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.
    - `validating_carrier` string
    - `fare_brand_code` string: 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.
    - `fare_brand_name` string: 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.
    - `legs` ExchangeOfferLeg[]: 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.
      - `stops` integer
      - `duration_minutes` number
      - `segments` ExchangeOfferSegment[]: The flown segments of this journey, in travel order.
        - `airline` string: IATA code of the MARKETING carrier — whose flight number this is.
        - `operating_carrier` string: IATA code of the carrier that flies the aircraft. Differs from `airline` on a codeshare.
        - `flight_number` string: 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.
        - `departure_airport` string
        - `departure_time` string: 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.
        - `arrival_airport` string
        - `arrival_time` string: 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.
        - `duration_minutes` number
        - `cabin_name` string: The cabin of the fare on this segment, as the airline names it.
        - `fare_brand_key` string: 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.
        - `fare_basis_code` string: The fare basis code the airline prices this segment with.
        - `rbd` string: The booking class (reservation booking designator) on this segment.
    - `fare_basis_codes` string[]: The fare basis codes of the alternative, in segment order.
    - `booking_classes` string[]: The booking classes of the alternative, in segment order.
    - `cabin` string
  - `warnings` string[]: 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.

## Other responses

- `400`: 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.
- `401`: Authentication required
- `402`: Payment required — organization balance exhausted
- `404`: Resource not found
- `409`: 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.
- `410`: The resource this request names no longer exists
- `422`: Validation error
- `429`: Rate limit or quota exceeded
- `502`: The travel provider rejected the request, or an upstream call failed
- `503`: No travel provider can serve the request right now
- `504`: The travel provider did not answer in time

---

[API](https://skmtc.dev/gojinko/apis/jinko-public-api.md) - [All operations](https://skmtc.dev/gojinko/apis/jinko-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/gojinko/apis/jinko-public-api/revisions/ac5046767e4c?raw)
