# API reference Source: https://docs.gojinko.com/api-reference/introduction The canonical reference for the Jinko Public API — request/response schemas, examples, and a try-it playground for every endpoint. This is the single canonical reference for everything the Jinko Public API exposes. Each endpoint page shows: * **Request / response schemas**, parameters, field types, examples * **A curl sample + try-it playground** — fill in values and run a request Prefer a typed client? The [TypeScript SDK](/connect/sdk) wraps these same endpoints with types and observability headers baked in. ## Base URL | Environment | Base URL | | ----------- | --------------------------------- | | Production | `https://api.gojinko.com` | | Sandbox | `https://api.sandbox.gojinko.com` | Production is the default. Use **sandbox** to test the full flow without touching prod data — it uses **separate API keys** (see [Sandbox keys](/authentication/api-keys#sandbox-keys)). All examples below use production. ## Authentication Authenticate every `/v1` request with your API key: ```http theme={null} X-API-Key: jnk_your_key ``` Or as a bearer token: `Authorization: Bearer jnk_your_key` Get a key from the [dashboard](https://gojinko.com/dashboard/keys). See [API keys](/authentication/api-keys) for detail. ## Observability We strongly recommend setting these on every request, they make debugging possible when something goes wrong: ```http theme={null} X-Session-ID: X-Request-ID: ``` Both land in the response headers too, so capture them on the client side. If you open a support ticket, include the `X-Request-ID` of the failing call. ## Response envelope Success: endpoint-specific JSON payload. Error: consistent envelope, same across all endpoints. ```json theme={null} { "error": { "code": "VALIDATION_FAILED", "message": "departure_date must be in the future", "details": { "field": "departure_date" } } } ``` See [Errors & troubleshooting](/concepts/errors) for the full status code reference. ## Typical request ```bash theme={null} curl https://api.gojinko.com/v1/flight_search \ -H "X-API-Key: jnk_..." \ -H "X-Request-ID: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "origin": "JFK", "destination": "CDG", "trip_type": "roundtrip", "departure_date": "2026-06-15", "return_date": "2026-06-22" }' ``` ## Endpoint groups Cache-backed search by route or destination (`flight_calendar`, `find_dates`, `lowest_fare`, `find_destination`, `price_monitoring`). Fast; stale-within-minutes prices. Live search + price-check via `flight_search`. Returns bookable `trip_item_token`. Live hotel search. `htl_*` tokens plug into the same trip as flights. Create a trip, add/remove items, upsert travelers, select ancillaries, then book. Guest lookup by `booking_ref` + `last_name`. Check eligibility → commit → poll status. Shop → price → commit → status (4-step flow). # book Source: https://docs.gojinko.com/api/book /api-reference/public-api.yaml POST /v1/book Schedule checkout for a trip — returns a checkout URL the user opens to complete payment Turn a finalized trip into a checkout link the user can pay through. Use it once the trip is set and traveler details are filled in, for example after the user picks a Paris to Tokyo round trip and adds a hotel for the stay. The returned URL is what the user opens in a browser to complete payment. # exchange commit Source: https://docs.gojinko.com/api/exchange/commit /api-reference/public-api.yaml POST /v1/exchange_commit Commit a flight exchange Execute a previously priced exchange. Poll [`exchange status`](/api/exchange/status) for terminal state. # exchange price Source: https://docs.gojinko.com/api/exchange/price /api-reference/public-api.yaml POST /v1/exchange_price Price a specific exchange offer Get the exact fare difference and penalty for a specific exchange option from [`exchange shop`](/api/exchange/shop) before committing. # exchange shop Source: https://docs.gojinko.com/api/exchange/shop /api-reference/public-api.yaml POST /v1/exchange_shop Shop for flight exchange alternatives List the alternative itineraries available to swap a booked flight onto. Pick one and price it with [`exchange price`](/api/exchange/price). # exchange status Source: https://docs.gojinko.com/api/exchange/status /api-reference/public-api.yaml POST /v1/exchange_status Check the status of an exchange Poll for terminal state of a previously committed exchange. # find-dates Source: https://docs.gojinko.com/api/find-dates /api-reference/public-api.yaml POST /v1/find_dates Best date options for a route — up to ten cheapest itineraries, one per date-pair, spread across the month Answers "when should I fly?" for a known route. Takes the same inputs as Flight Calendar but returns up to ten cheapest itineraries — one per (departure, return) date-pair — spread across the requested departure window, so the user gets a diverse shortlist rather than ten near-adjacent cheapest days. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. # find-destination Source: https://docs.gojinko.com/api/find-destination /api-reference/public-api.yaml POST /v1/find_destination Discover travel destinations accessible from your departure airports Surface inspiration when a user knows where they want to leave from but not where they want to go. Typical prompts include "cheap beach getaways from New York" or "weekend trips out of London under €200". Results come back ranked by lowest available fare so the user can compare options before committing to a route. # flight-calendar Source: https://docs.gojinko.com/api/flight-calendar /api-reference/public-api.yaml POST /v1/flight_calendar Search flights between a known origin and destination for flexible dates Find priced itineraries between a known origin and destination using cached results, ideal when the user is flexible on dates. It answers questions like "cheapest week to fly Paris to Barcelona in June" or "best Friday to Sunday options from JFK to LAX next month". Each result includes an offer token you can pass into a live price check or directly into a trip. # flight-search Source: https://docs.gojinko.com/api/flight-search /api-reference/public-api.yaml POST /v1/flight_search Get live flight pricing — search by route, or re-price a known offer Fetch live, bookable pricing for a specific route and date pair. Use it once the user has settled on exact travel dates, for example "Paris to New York departing June 1 returning June 8 in economy". It also reprices an offer surfaced earlier by the calendar or destination tools so you can confirm availability before adding it to a trip. ## Two modes, one endpoint `POST /v1/flight_search` serves both modes: * **Search mode** — filter-based live search by `origin`, `destination`, `departure_date`, and passengers. Returns priced offers, each fare carrying a `trip_item_token` you can add to a [trip](/api/trip). * **Reprice mode** — pass an `offer_token` from discovery (`find_destination`, `flight_calendar`) to re-price that specific offer before adding it to a trip. The other route fields are ignored when `offer_token` is present. The CLI mirrors this: pass `--offer-token` for reprice mode, omit it for search mode. # get-booking Source: https://docs.gojinko.com/api/get-booking /api-reference/public-api.yaml POST /v1/get_booking Retrieve a booking using the Jinko booking reference and the traveler's last name Anonymous retrieval for a booking the user already made. Use it when the traveler has their Jinko booking reference and last name, for example to look up the itinerary days later without signing in. Returns the full booking envelope: status, travelers, and itinerary items with confirmation numbers (PNR for flights, confirmation number for hotels). # hotel-cancel Source: https://docs.gojinko.com/api/hotel-cancel /api-reference/public-api.yaml POST /v1/hotel_cancel Cancel a hotel booking and get a refund when eligible Cancel a hotel booking when the traveler can no longer make the stay or wants to drop a hotel from a multi-item trip. The call is idempotent: retrying the same cancellation re-serves the stored result rather than charging or refunding twice. Works with guest auth (booking ref + last name) or the authenticated shortcut (provider booking ID). Two auth modes: * **Guest** — `booking_ref` + `last_name` together. * **Authenticated** — `provider_booking_id` (optionally with `provider`). The two modes are mutually exclusive. # hotel-details Source: https://docs.gojinko.com/api/hotel-details /api-reference/public-api.yaml GET /v1/hotel_details/{hotel_id} Fetch rich metadata (gallery, facilities, policies, per-room details) for a single hotel Pull the full marketing and operational profile of a single property after a search result catches the user's attention. Useful for questions like "what amenities does this hotel have", "is there a pool on site", or "what is the cancellation policy on the deluxe room". Returns the gallery, facilities, room metadata, and policies in one payload. # hotel-search Source: https://docs.gojinko.com/api/hotel-search /api-reference/public-api.yaml POST /v1/hotel_search Search live hotel inventory and rates Search live hotel inventory and nightly rates for a destination and stay window. It handles requests like "three nights in Lisbon next weekend for two adults" or "family room in Rome with one child in August". Each result includes an `htl_*` offer token you can hand to the trip tool to start a booking. # lowest-fare Source: https://docs.gojinko.com/api/lowest-fare /api-reference/public-api.yaml POST /v1/lowest_fare Cheapest fares for a fixed route + date — up to ten itineraries, cheapest first The cheapest fares for a fixed route and date. Takes the same inputs as Flight Calendar but for one specific departure date (one-way, or with a return date for round-trip) returns up to ten itineraries sorted cheapest-first. The fixed-date counterpart of Flight Calendar — reach for it when the date is locked and you just want the cheapest options that day. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. # price-monitoring Source: https://docs.gojinko.com/api/price-monitoring /api-reference/public-api.yaml POST /v1/price_monitoring Monitor price for a specific origin, destination, and dates pair Watch a specific route and date pair over time so an agent can act when the fare drops. Use it for prompts like "alert me when Paris to New York for June 17 to 26 goes under €400". Each response includes the current cheapest cached fare and an offer token you can pass to flight\_search when the user decides to book. Cache-only; never triggers a live call. # refund check Source: https://docs.gojinko.com/api/refund/check /api-reference/public-api.yaml POST /v1/refund_check Check refund eligibility and estimated amount Run first when a user asks to cancel: shows refund amount, penalties, and whether processing is automatic. # refund commit Source: https://docs.gojinko.com/api/refund/commit /api-reference/public-api.yaml POST /v1/refund_commit Initiate a refund for a booked flight Issue the refund after the user has reviewed the amount and confirmed cancellation. Poll [`refund status`](/api/refund/status) for terminal state. # refund status Source: https://docs.gojinko.com/api/refund/status /api-reference/public-api.yaml POST /v1/refund_status Check the status of a refund Poll for terminal state of a previously committed refund. # select-ancillaries Source: https://docs.gojinko.com/api/select-ancillaries /api-reference/public-api.yaml POST /v1/select_ancillaries Select ancillaries (baggage, seats, meals) for a trip item Add baggage, seat selections, or meals to a flight item before checkout. Use it after the trip has a flight item and travelers attached but before `book`, for example when a user requests "two checked bags and a window seat for the outbound leg". Selections use full-replacement semantics — include everything the user wants kept on the trip in a single call. # trip Source: https://docs.gojinko.com/api/trip /api-reference/public-api.yaml POST /v1/trip Create and manage a trip — add or remove items, set travelers, select ancillaries Assemble and edit a trip before sending it to checkout. Use it to add a flight or hotel offer, set traveler details, swap one item for another, or attach ancillaries like bags and seats. Flights and hotels can sit side by side in the same trip and settle through a single checkout. Unified trip management endpoint. In a single call you can `add_item` (by `trip_item_token`), `remove_item` (by `item_id`), and `upsert_travelers` (travelers + contact). Omit `trip_id` to create a new trip; include it to update an existing one. Returns the resulting trip state. Ancillaries are selected on a separate endpoint — see [select-ancillaries](/api/select-ancillaries). # trip-status Source: https://docs.gojinko.com/api/trip-status /api-reference/public-api.yaml GET /v1/trip/{trip_id} Fetch the full lifecycle state of a trip — items, travelers, quote, fulfillment, and any booking references Inspect the current state of a trip without modifying it. Reach for it when you need to confirm what items are on the trip, verify the travelers attached to a booking, or check whether a checkout has finalized after the user paid. The response covers items, traveler details, quote status, and any booking references that have been issued. # trip ancillaries Source: https://docs.gojinko.com/api/trip/ancillaries /api-reference/public-api.yaml GET /v1/trip/{trip_id}/ancillaries List purchasable ancillaries for a trip (no checkout) Returns the available ancillaries for a trip without generating a checkout URL. A price quote runs transparently behind the BFF (TravelFusion only emits the ancillary catalog at pricing time) 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. # webhooks Source: https://docs.gojinko.com/api/webhooks /api-reference/public-api.yaml DELETE /v1/webhooks/{id} Delete a webhook subscription Delete a webhook subscription # webhooks test Source: https://docs.gojinko.com/api/webhooks/test /api-reference/public-api.yaml POST /v1/webhooks/{id}/test Send a sample signed event to validate the endpoint Delivers a `livemode: false` sample event so you can verify signature + connectivity without a real booking. # API keys Source: https://docs.gojinko.com/authentication/api-keys Get and use API keys (jnk_*) for programmatic access to Jinko. API keys are the simplest way to authenticate with Jinko. They prefix with `jnk_` and work everywhere, the [SDK](/connect/sdk), the [CLI](/connect/cli), MCP clients, and direct [REST](/api-reference/introduction) calls. Use them for: agents, scripts, CI/CD, server-side apps, MCP clients without OAuth support. Don't use them for: end-user-facing OAuth flows in MCP clients that support [DCR](/authentication/oauth) (Claude Desktop, ChatGPT, Cursor, Codex, Openclaw). ## Get a key [gojinko.com/dashboard/keys](https://gojinko.com/dashboard/keys) First time? You'll be auto-onboarded via Jinko Auth, no waitlist. Hit **Create key**, name it something memorable. Default monthly quota is 1,000 requests. The full key is only shown once at creation. Store it somewhere safe (1Password, your secrets manager, etc.) before navigating away. If you lose it, just rotate, make a new one and delete the old. ## Use a key ```typescript theme={null} import { createJinkoClient } from '@gojinko/api-client' const client = await createJinkoClient({ apiKey: 'jnk_...' }) ``` Or via env: `export JINKO_API_KEY=jnk_...` and call `createJinkoClient()` with no args. ```bash theme={null} # Persist to ~/.jinko/config.yaml jinko auth login --key jnk_... # Or use an env var (no login needed) export JINKO_API_KEY=jnk_... jinko flight-calendar --origins CDG --destinations JFK --month 2026-06 ``` Attach as an `Authorization: Bearer` header on the MCP endpoint: ```bash theme={null} claude mcp add --transport http jinko https://mcp.builders.gojinko.com/mcp \ --header "Authorization: Bearer jnk_..." ``` See [Connect via API key](/quickstart#connect-via-api-key) for client-specific configs. ```bash theme={null} curl https://api.gojinko.com/v1/flight_search \ -H "X-API-Key: jnk_..." \ -H "Content-Type: application/json" \ -d '{ "origin": "JFK", "destination": "CDG", "trip_type": "oneway", "departure_date": "2026-06-15" }' ``` The REST API accepts both `X-API-Key: jnk_...` and `Authorization: Bearer jnk_...`. A `jnk_` key is one of two auth methods on every `/v1` route — the other is [WorkOS OAuth](/authentication/oauth) via `Authorization: Bearer `. ## Sandbox keys Jinko runs two isolated environments — **production** and **sandbox** (test the full flow without touching prod data). They use **separate keys**: a `jnk_` key is scoped to the environment it was created in and won't authenticate against the other. Generate a sandbox key from the dashboard, then point your client at the matching base URL: | Surface | Production | Sandbox | | ---------- | -------------------------------------- | ---------------------------------------------- | | REST / SDK | `https://api.gojinko.com` | `https://api.sandbox.gojinko.com` | | MCP | `https://mcp.builders.gojinko.com/mcp` | `https://mcp.builders.sandbox.gojinko.com/mcp` | | CLI | default | `--env sandbox` | The [CLI](/connect/cli#environments-prod-sandbox) and [SDK](/connect/sdk#environments-prod-sandbox) have built-in environment switching (they store the two keys separately); for REST/MCP just use the sandbox URL above with your sandbox key. ## Rotation If a key leaks (committed to git, posted in chat, etc.): 1. Create a new key in the dashboard. 2. Update your scripts / env / config to use the new key. 3. Delete the old key in the dashboard. **Anything still using it stops working immediately.** Always rotate; never edit a key in place. There's no rate-limited grace period. ## Quotas Free tier: 1,000 requests / 30 days, per key. Quota counters are per key, splitting work across multiple keys doesn't help. Need more? Email [dev@gojinko.com](mailto:dev@gojinko.com) with your use case and we'll bump it. ## Common failures | Symptom | Likely cause | Fix | | -------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | | `401 Unauthorized` | Key missing, mistyped, or revoked | Verify the key in the dashboard; check for whitespace at start/end | | `401` with `unexpected iss claim` | You're sending a CLI **OAuth** token, not an API key | Use a `jnk_*` key instead, see [OAuth](/authentication/oauth) for why | | `429 Too Many Requests` | Monthly quota exhausted | Email [dev@gojinko.com](mailto:dev@gojinko.com) or wait for the next billing window | | `403 Forbidden` on a specific endpoint | Endpoint requires a higher tier or a permission your account lacks | Check the dashboard for plan info; reach out if surprised | For `4xx` debugging, also check the response body, Jinko returns a structured `error` object with a code and message. See [Errors & troubleshooting](/concepts/errors). # OAuth Source: https://docs.gojinko.com/authentication/oauth Browser-based auth for MCP clients (DCR) and the CLI (device flow). Jinko supports two distinct OAuth flows. Both go through Jinko Auth at `auth.gojinko.com`. | Flow | Used by | Issuer | | ---------------------------------------------------- | ------------------------------------------------ | ------------------------------------------- | | **MCP OAuth** with Dynamic Client Registration (DCR) | Claude Desktop, ChatGPT, Cursor, Codex, Openclaw | AuthKit (`auth.gojinko.com`) | | **CLI device flow** | `@gojinko/cli` (`jinko auth login`) | Jinko Auth user pool (Jinko Auth user pool) | These tokens are **not interchangeable.** A token from `jinko auth login` will fail with `unexpected iss claim` if you paste it into an MCP client's `Authorization: Bearer` header. Use an [API key](/authentication/api-keys) for programmatic MCP access. ## MCP OAuth (DCR) Best path for end-user-facing MCP clients. Zero config, the client discovers Jinko's auth server, registers itself dynamically, and runs OAuth 2.1 + PKCE in the user's browser. ### Supported clients * **Claude Desktop** / Claude Web, Settings → Connectors → Add custom connector. Just enter `https://mcp.builders.gojinko.com/mcp` and leave OAuth fields blank. * **Claude Code**, `claude mcp add --transport http jinko https://mcp.builders.gojinko.com/mcp` * **ChatGPT**, Add the connector in the desktop or web app's MCP settings. * **Cursor**, Settings → MCP Servers → Add Server with the endpoint URL. ### What happens under the hood Client GETs `https://mcp.builders.gojinko.com/.well-known/oauth-authorization-server` to learn the auth server (`auth.gojinko.com`). Client POSTs to the registration endpoint to mint itself a client\_id + secret. No human in the loop. Client opens a browser to `auth.gojinko.com`, user signs in or signs up. Jinko Auth redirects back with an auth code. Client trades the code for an access token (and refresh token). Stored locally per the client's conventions. On first use, our API pulls the JWT `sub` claim and provisions a Jinko devplatform user, no waitlist, no manual approval. Tokens auto-refresh on the client side; you don't manage anything. ## CLI OAuth (device flow) Used when you run `jinko auth login` and pick the OAuth path (default). ```bash theme={null} jinko auth login # → "Open this URL in any browser to sign in: https://auth.gojinko.com/device" # → "Code: ABCD-1234" ``` Works over SSH and remote sessions (the URL + code are decoupled from the local browser). Tokens land in `~/.jinko/config.yaml`. The SDK and CLI both pick them up. The CLI auto-refreshes tokens before each request when `expires_at` is near. To clear: `jinko auth logout` (removes both OAuth tokens and any saved API key from the config). ## WorkOS OAuth on the REST API Every `/v1` route on `api.gojinko.com` accepts a WorkOS OAuth access token as a bearer — the same token the CLI device flow mints — alongside `jnk_` API keys: ```bash theme={null} curl https://api.gojinko.com/v1/flight_search \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "origin": "JFK", "destination": "CDG", "trip_type": "oneway", "departure_date": "2026-06-15" }' ``` The REST gateway forwards the bearer to the BFF, which verifies it and resolves your user identity. So the two REST auth methods are **`jnk_` via `X-API-Key`** and **WorkOS OAuth via `Authorization: Bearer`** — both work on every `/v1` route. The SDK and CLI use a token from `jinko auth login` automatically once you're logged in. This is distinct from the MCP endpoint. The "issuer mismatch" caveat above is specific to pasting a CLI token into an **MCP** client's `Authorization: Bearer` header — on the REST `/v1` surface the bearer is forwarded and verified by the BFF. ## Which auth should I use? | Scenario | Recommended | | -------------------------------------------- | ---------------------------------------------------------- | | Building an MCP server / agent for end users | **MCP OAuth** (DCR), zero config | | Server-side script, CI, agent backend | **API key**, long-lived, no refresh logic | | Local dev with the CLI | **CLI OAuth** (device flow), your account, no separate key | | Single-script automation on a workstation | Either works; OAuth keeps you out of the keys dashboard | When in doubt, an API key is the most portable option. ## Common failures | Symptom | Cause | Fix | | ------------------------------------------ | ------------------------------------------------------------------ | --------------------------------------------------------------------------- | | `401 unexpected iss claim` on MCP endpoint | You pasted a CLI OAuth token where a JWT-from-AuthKit was expected | Use an API key (`jnk_...`) on MCP, or use a client that supports DCR | | MCP client can't reach the auth server | Network / proxy blocking `auth.gojinko.com` | Whitelist `auth.gojinko.com`, `mcp.builders.gojinko.com`, `api.gojinko.com` | | CLI device flow times out | Code expired before user completed the browser step (\~10 min) | Re-run `jinko auth login` | | Token refresh fails after long idle | Refresh token also expired | `jinko auth login` again | See [Errors & troubleshooting](/concepts/errors) for HTTP-level debugging. # jinko auth login Source: https://docs.gojinko.com/cli/auth/login Authenticate with Jinko (OAuth or API key). Authenticate with Jinko (OAuth or API key). ## Usage ```bash theme={null} jinko auth login [options] ``` ## Options | Flag | Required | Description | Default | | --------------- | -------- | -------------------------------------------- | ------- | | `--key ` | No | API key (jnk\_...) — skip interactive prompt | | ## Examples ```bash theme={null} # OAuth (browser device flow, works over SSH too) jinko auth login # API key (skip the browser) jinko auth login --key jnk_your_key ``` Tokens + key land in `~/.jinko/config.yaml`. The SDK picks them up automatically. # jinko auth logout Source: https://docs.gojinko.com/cli/auth/logout Clear stored credentials. Clear stored credentials. ## Usage ```bash theme={null} jinko auth logout [options] ``` ## Options *No options.* ## Examples ```bash theme={null} jinko auth logout ``` Clears OAuth tokens and any API key from `~/.jinko/config.yaml`. The session file (`~/.jinko/session.yaml`) is untouched, delete it manually if you want a fresh session ID. # jinko auth status Source: https://docs.gojinko.com/cli/auth/status Show current authentication status. Show current authentication status. ## Usage ```bash theme={null} jinko auth status [options] ``` ## Options *No options.* ## Examples ```bash theme={null} jinko auth status # → method: oauth # expires_at: 2026-04-21T18:30:00Z # user_id: user_abc... ``` # jinko book Source: https://docs.gojinko.com/cli/book Schedule checkout for a trip — returns a checkout URL the user opens to complete payment Turn a finalized trip into a checkout link the user can pay through. Use it once the trip is set and traveler details are filled in, for example after the user picks a Paris to Tokyo round trip and adds a hotel for the stay. The returned URL is what the user opens in a browser to complete payment. ## Usage ```bash theme={null} jinko book [options] ``` ## Options | Flag | Required | Description | Default | | ---------------- | -------- | --------------------------- | ------- | | `--trip-id ` | Yes | trip ID (from trip command) | | ## Examples ```bash theme={null} # Schedule checkout, get the Stripe URL jinko book --trip-id 42 # → { "checkout_url": "https://app.gojinko.com/checkout?sid=..." } ``` Open the `checkout_url` in a browser. Stripe webhooks fulfill the booking, no confirm step needed. # jinko config set Source: https://docs.gojinko.com/cli/config/set Set a config value. Keys: api_key, environment Set a config value. Keys: api\_key, environment ## Usage ```bash theme={null} jinko config set [options] ``` ### Arguments | Argument | Required | Description | | -------- | -------- | ----------- | | `key` | Yes | | | `value` | Yes | | ## Options *No options.* ## Examples ```bash theme={null} # Switch the active environment (prod | sandbox) jinko config set environment sandbox # Store an API key under the active environment jinko config set api_key jnk_your_key ``` # jinko config show Source: https://docs.gojinko.com/cli/config/show Show current configuration. Show current configuration. ## Usage ```bash theme={null} jinko config show [options] ``` ## Options *No options.* ## Examples ```bash theme={null} jinko config show # Dumps the current ~/.jinko/config.yaml (secrets masked) ``` # jinko exchange commit Source: https://docs.gojinko.com/cli/exchange/commit Commit a flight exchange Execute a flight exchange. ## Usage ```bash theme={null} jinko exchange commit [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--offer-id ` | Yes | exchange offer ID | | | `--session-reference ` | Yes | session reference from price response | | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | | `--ticket-numbers ` | No | one or more ticket numbers | | ## Examples ```bash theme={null} jinko exchange commit \ --booking-ref JNK-ABC123 \ --last-name Doe \ --offer-id exch_offer_abc \ --session-reference sess_xyz789 ``` Returns an `exchange_reference`. Poll `jinko exchange status` until terminal. # jinko exchange price Source: https://docs.gojinko.com/cli/exchange/price Price a specific exchange offer Price a specific exchange offer. ## Usage ```bash theme={null} jinko exchange price [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--offer-id ` | Yes | exchange offer ID from shop response | | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | | `--ticket-numbers ` | No | one or more ticket numbers | | ## Examples ```bash theme={null} jinko exchange price \ --booking-ref JNK-ABC123 \ --last-name Doe \ --offer-id exch_offer_abc ``` Returns `price_delta`, `airline_penalty`, `service_fee`, and a `session_reference` to commit against. # jinko exchange shop Source: https://docs.gojinko.com/cli/exchange/shop Shop for flight exchange alternatives Shop for flight exchange alternatives. ## Usage ```bash theme={null} jinko exchange shop [options] ``` ## Options | Flag | Required | Description | Default | | ----------------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | | `--ticket-numbers ` | No | one or more ticket numbers | | | `--preferred-departure-date ` | No | preferred departure date (YYYY-MM-DD) | | ## Examples ```bash theme={null} jinko exchange shop \ --booking-ref JNK-ABC123 \ --last-name Doe \ --new-departure-date 2026-07-15 ``` Returns alternative itineraries with `offer_id` values, pick one and pass to `jinko exchange price`. # jinko exchange status Source: https://docs.gojinko.com/cli/exchange/status Check the status of an exchange Poll the status of an in-flight exchange. ## Usage ```bash theme={null} jinko exchange status [options] ``` ## Options | Flag | Required | Description | Default | | ----------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | ## Examples ```bash theme={null} jinko exchange status \ --booking-ref JNK-ABC123 \ --last-name Doe \ --exchange-reference EXC-abc123 ``` Terminal states: `succeeded`, `failed`. Poll every 15-30s. # jinko find-dates Source: https://docs.gojinko.com/cli/find-dates Best date options for a route — up to ten cheapest itineraries, one per date-pair, spread across the month Answers "when should I fly?" for a known route. Takes the same inputs as Flight Calendar but returns up to ten cheapest itineraries — one per (departure, return) date-pair — spread across the requested departure window, so the user gets a diverse shortlist rather than ten near-adjacent cheapest days. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. ## Usage ```bash theme={null} jinko find-dates [options] ``` ## Options | Flag | Required | Description | Default | | --------------------------- | -------- | ------------------------------------------------------------------------------------------------ | ------- | | `--origins ` | Yes | origin IATA airport/city codes. JSON: `origins[]`. | | | `--destinations ` | No | destination IATA airport/city codes. Omit to scan all destinations. JSON: `destinations[]`. | | | `--month ` | No | departure month to scan (YYYY-MM), defaults to current month | | | `--trip-type ` | No | oneway or roundtrip (default: roundtrip). JSON: `trip_type`. | | | `--stay-days ` | No | nights away for a roundtrip (default: 7). JSON: `stay_days`. | | | `--cabin-class ` | No | cabin class: economy, premium\_economy, business, first (default: economy). JSON: `cabin_class`. | | | `--direct-only` | No | only direct flights. JSON: `direct_only`. | | | `--limit ` | No | max date-pairs to return (1-100, default 20). JSON: `limit`. | | | `--from ` | No | DEPRECATED: use --origins. | | | `--to ` | No | DEPRECATED: use --destinations. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | # jinko find-destination Source: https://docs.gojinko.com/cli/find-destination Discover travel destinations accessible from your departure airports Surface inspiration when a user knows where they want to leave from but not where they want to go. Typical prompts include "cheap beach getaways from New York" or "weekend trips out of London under €200". Results come back ranked by lowest available fare so the user can compare options before committing to a route. ## Usage ```bash theme={null} jinko find-destination [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- | ----------- | | `--origins ` | Yes | IATA airport or city codes (e.g. JFK LGA). JSON: `origins[]`. | | | `--destinations ` | No | IATA airport or city codes to filter to. Omit for global discovery. JSON: `destinations[]`. | | | `--origin-type ` | No | How to interpret --origins: `city` or `airport` (default: `city`). JSON: `origin_type`. | | | `--destination-type ` | No | How to interpret --destinations: `city` or `airport` (default: `city`). JSON: `destination_type`. | | | `--departure-dates ` | No | Exact departure dates (YYYY-MM-DD), OR logic. JSON: `departure_dates[]`. | | | `--departure-date-ranges ` | No | Flexible departure ranges, repeatable. Format: `YYYY-MM-DD:YYYY-MM-DD`. JSON: `departure_date_ranges[]`. | | | `--return-dates ` | No | Exact return dates (YYYY-MM-DD), roundtrip only. JSON: `return_dates[]`. | | | `--return-date-ranges ` | No | Flexible return ranges, roundtrip only. Format: `YYYY-MM-DD:YYYY-MM-DD`. JSON: `return_date_ranges[]`. | | | `--stay-days ` | No | Exact stay length in days. JSON: `stay_days`. | | | `--stay-days-range ` | No | Flexible stay range, e.g. `5:10`. JSON: `stay_days_range`. | | | `--trip-type ` | No | `oneway` or `roundtrip` (inferred from --return-dates if omitted). JSON: `trip_type`. | | | `--cabin-class ` | No | `economy`, `premium_economy`, `business`, or `first` (default: `economy`). JSON: `cabin_class`. | `"economy"` | | `--direct-only` | No | Only return nonstop flights. JSON: `direct_only`. | | | `--adults ` | No | Adult passengers (default: 1). JSON: `adults`. | | | `--children ` | No | Child passengers. JSON: `children`. | | | `--infants-in-lap ` | No | Infants on lap (no seat). JSON: `infants_in_lap`. | | | `--infants-in-seat ` | No | Infants in own seat. JSON: `infants_in_seat`. | | | `--youth ` | No | Youth fare. JSON: `passengers.youth`. | | | `--student ` | No | Student fare. JSON: `passengers.student`. | | | `--ages ` | No | Explicit ages array (alternative to counts). JSON: `ages[]`. | | | `--residency-country ` | No | Residency country, ISO 3166-1 alpha-2. JSON: `residency_country`. | | | `--max-total ` | No | Maximum total price in --currency. JSON: `max_total`. | | | `--currency ` | No | ISO 4217 currency code (default: USD). JSON: `currency`. | | | `--locale ` | No | BCP 47 locale, e.g. `en-US`, `fr-FR` (default: `en-US`). JSON: `locale`. | | | `--limit ` | No | Maximum destinations (1-100, default 20). JSON: `limit`. | `"20"` | | `--offset ` | No | Pagination offset (default 0). JSON: `offset`. | | | `--flights-per-destination ` | No | Itineraries per destination (1-10, default 1). JSON: `flights_per_destination`. | | | `--sort-by ` | No | `lowest` or `recommendation` (default: `lowest`). JSON: `sort_by`. | `"lowest"` | | `--from ` | No | DEPRECATED: use --origins. | | | `--date ` | No | DEPRECATED: use --departure-dates. | | | `--return ` | No | DEPRECATED: use --return-dates. | | | `--departure-range ` | No | DEPRECATED: use --departure-date-ranges. | | | `--stay ` | No | DEPRECATED: use --stay-days-range. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | | `--max-price ` | No | DEPRECATED: use --max-total. | | | `--sort ` | No | DEPRECATED: use --sort-by. | | ## Examples Discover destinations reachable from your origins within a budget and date window: ```bash theme={null} jinko find-destination \ --origins JFK LGA EWR \ --departure-date-ranges 2026-06-01:2026-06-30 \ --stay-days-range 5:10 \ --trip-type roundtrip \ --adults 2 \ --max-total 500 \ --currency USD ``` The equivalent REST and SDK calls live in the [API reference](/api/find-destination). # jinko flight-calendar Source: https://docs.gojinko.com/cli/flight-calendar Search flights between a known origin and destination for flexible dates Find priced itineraries between a known origin and destination using cached results, ideal when the user is flexible on dates. It answers questions like "cheapest week to fly Paris to Barcelona in June" or "best Friday to Sunday options from JFK to LAX next month". Each result includes an offer token you can pass into a live price check or directly into a trip. ## Usage ```bash theme={null} jinko flight-calendar [options] ``` ## Options | Flag | Required | Description | Default | | --------------------------- | -------- | ------------------------------------------------------------------------------------------------ | ------- | | `--origins ` | Yes | origin IATA airport/city codes. JSON: `origins[]`. | | | `--destinations ` | No | destination IATA airport/city codes. Omit to scan all destinations. JSON: `destinations[]`. | | | `--month ` | No | month to display (YYYY-MM), defaults to current month | | | `--cabin-class ` | No | cabin class: economy, premium\_economy, business, first (default: economy). JSON: `cabin_class`. | | | `--direct-only` | No | only direct flights. JSON: `direct_only`. | | | `--limit ` | No | max results to return per page (1-100, default 20). JSON: `limit`. | | | `--offset ` | No | number of results to skip, for pagination (default 0). JSON: `offset`. | | | `--from ` | No | DEPRECATED: use --origins. | | | `--to ` | No | DEPRECATED: use --destinations. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | ## Examples ```bash theme={null} # Cheapest days JFK → CDG in June jinko flight-calendar --origins JFK --destinations CDG --month 2026-06 ``` # jinko flight-search Source: https://docs.gojinko.com/cli/flight-search Get live flight pricing — search by route, or re-price a known offer Fetch live, bookable pricing for a specific route and date pair. Use it once the user has settled on exact travel dates, for example "Paris to New York departing June 1 returning June 8 in economy". It also reprices an offer surfaced earlier by the calendar or destination tools so you can confirm availability before adding it to a trip. ## Usage ```bash theme={null} jinko flight-search [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------ | ------- | | `--origin ` | Yes — search mode | origin IATA code (e.g. PAR for city, JFK for airport). JSON: `origin`. | | | `--destination ` | Yes — search mode | destination IATA code (e.g. NYC for city, LAX for airport). JSON: `destination`. | | | `--departure-date ` | Yes — search mode | departure date (YYYY-MM-DD). JSON: `departure_date`. | | | `--return-date ` | No | return date for round-trip (YYYY-MM-DD). JSON: `return_date`. | | | `--cabin-class ` | No | cabin class: economy, premium\_economy, business, first (default: economy). JSON: `cabin_class`. | | | `--adults ` | No | number of adult passengers (default: 1). JSON: `adults`. | | | `--direct-only` | No | only show direct flights. JSON: `direct_only`. | | | `--max-price ` | No | maximum price filter. JSON: `max_price`. | | | `--include-carriers ` | No | include only these IATA 2-letter carrier codes (e.g. AF KL). JSON: `include_carriers`. | | | `--exclude-carriers ` | No | exclude these IATA 2-letter carrier codes (e.g. FR U2). JSON: `exclude_carriers`. | | | `--limit ` | No | max results to return (1-100, default 20). Search mode only. JSON: `limit`. | | | `--offer-token ` | Yes — price-check mode | price-check a specific offer (live pricing). JSON: `offer_token`. | | | `--from ` | No | DEPRECATED: use --origin. | | | `--to ` | No | DEPRECATED: use --destination. | | | `--date ` | No | DEPRECATED: use --departure-date. | | | `--return ` | No | DEPRECATED: use --return-date. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | | `--passengers ` | No | DEPRECATED: use --adults. | | | `--origin-type ` | No | DEPRECATED: ignored by the public contract (no longer sent). | | | `--destination-type ` | No | DEPRECATED: ignored by the public contract (no longer sent). | | ## Examples ```bash theme={null} # Price-check a discovery offer jinko flight-search --offer-token "$OFFER_TOKEN" --format json | jq '.fares[0]' # Live search by route jinko flight-search --origin CDG --destination JFK --departure-date 2026-06-15 --return-date 2026-06-22 \ --adults 2 --cabin-class economy --format json ``` # jinko get-booking Source: https://docs.gojinko.com/cli/get-booking Retrieve a booking using the Jinko booking reference and the traveler's last name Anonymous retrieval for a booking the user already made. Use it when the traveler has their Jinko booking reference and last name, for example to look up the itinerary days later without signing in. Returns the full booking envelope: status, travelers, and itinerary items with confirmation numbers (PNR for flights, confirmation number for hotels). ## Usage ```bash theme={null} jinko get-booking [options] ``` ## Options | Flag | Required | Description | Default | | --------------------- | -------- | --------------------------------------------------------------- | ------- | | `--booking-ref ` | Yes | Jinko booking reference (e.g. JNK-A7B3X9). JSON: `booking_ref`. | | | `--last-name ` | Yes | Last name of the primary traveler. JSON: `last_name`. | | | `--ref ` | No | DEPRECATED: use --booking-ref. | | ## Examples ```bash theme={null} jinko get-booking --booking-ref JNK-ABC123 --last-name Doe ``` No auth needed, this is the guest endpoint. Returns the booking envelope or a generic 404 (existence non-leak). # jinko hotel-cancel Source: https://docs.gojinko.com/cli/hotel-cancel Cancel a hotel booking and get a refund when eligible Cancel a hotel booking when the traveler can no longer make the stay or wants to drop a hotel from a multi-item trip. The call is idempotent: retrying the same cancellation re-serves the stored result rather than charging or refunding twice. Works with guest auth (booking ref + last name) or the authenticated shortcut (provider booking ID). ## Usage ```bash theme={null} jinko hotel-cancel [options] ``` ## Options | Flag | Required | Description | Default | | ---------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (e.g. JNK-A7B3X9). Guest path — pair with --last-name. JSON: `booking_ref`. | | | `--last-name ` | Yes — guest mode | Last name of the lead guest. Guest path — pair with --booking-ref. JSON: `last_name`. | | | `--provider-booking-id ` | Yes — authenticated mode | Provider booking ID (authenticated shortcut). Mutually exclusive with --booking-ref + --last-name. JSON: `provider_booking_id`. | | | `--provider ` | No | Provider code (e.g. "nuitee"). Optional, only meaningful with --provider-booking-id. JSON: `provider`. | | | `--ref ` | No | DEPRECATED: use --booking-ref. | | # jinko hotel-details Source: https://docs.gojinko.com/cli/hotel-details Fetch rich metadata (gallery, facilities, policies, per-room details) for a single hotel Pull the full marketing and operational profile of a single property after a search result catches the user's attention. Useful for questions like "what amenities does this hotel have", "is there a pool on site", or "what is the cancellation policy on the deluxe room". Returns the gallery, facilities, room metadata, and policies in one payload. ## Usage ```bash theme={null} jinko hotel-details [options] ``` ## Options | Flag | Required | Description | Default | | ------------------- | -------- | -------------------------------------------------------------------------------------------------- | ------- | | `--hotel-id ` | Yes | hotel ID (from a prior hotel-search offer) | | | `--checkin ` | No | check-in date (YYYY-MM-DD) — accepted for future cache-key alignment, currently unused by the BFF | | | `--checkout ` | No | check-out date (YYYY-MM-DD) — accepted for future cache-key alignment, currently unused by the BFF | | ## Examples ```bash theme={null} # Minimal — just the hotel ID returned by hotel-search jinko hotel-details --hotel-id lpe2264 # With dates for cache alignment jinko hotel-details --hotel-id lpe2264 --checkin 2026-07-15 --checkout 2026-07-18 ``` # jinko hotel-search Source: https://docs.gojinko.com/cli/hotel-search Search live hotel inventory and rates Search live hotel inventory and nightly rates for a destination and stay window. It handles requests like "three nights in Lisbon next weekend for two adults" or "family room in Rome with one child in August". Each result includes an `htl_*` offer token you can hand to the trip tool to start a booking. ## Usage ```bash theme={null} jinko hotel-search [options] ``` ## Options | Flag | Required | Description | Default | | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `--query ` | No | free-text destination (city, region, POI) — Mode B. JSON: `query`. | | | `--city-name ` | No | city name (e.g. "Paris") — Mode B destination, or Mode A lookup scope when combined with --hotel-name. JSON: `city_name`. | | | `--country-code ` | No | ISO 3166-1 alpha-2 country code (e.g. fr) — Mode B destination, or Mode A lookup scope when combined with --hotel-name. JSON: `country_code`. | | | `--latitude ` | No | latitude for geo-radius search — Mode B. JSON: `latitude`. | | | `--longitude ` | No | longitude for geo-radius search — Mode B. JSON: `longitude`. | | | `--radius-km ` | No | search radius in km (default 5, max 50) — Mode B. JSON: `radius_km`. | | | `--place-id ` | No | Google Places ID or upstream place identifier — Mode B. JSON: `place_id`. | | | `--hotel-ids ` | No | re-shop specific hotel IDs — Mode A. JSON: `hotel_ids`. | | | `--hotel-name ` | No | look up a specific hotel by name — Mode A. Pair with --city-name and --country-code to narrow the lookup scope. | | | `--checkin ` | Yes | check-in date (YYYY-MM-DD). JSON: `checkin`. | | | `--checkout ` | Yes | check-out date (YYYY-MM-DD). JSON: `checkout`. | | | `--adults ` | No | number of adults (shorthand). JSON: `adults`. | `"2"` | | `--children ` | No | children ages (shorthand, e.g. 5 7). JSON: `children`. | | | `--rooms ` | No | number of rooms (shorthand). JSON: `rooms`. | | | `--currency ` | No | ISO 4217 currency code (default USD). JSON: `currency`. | | | `--guest-nationality ` | No | guest nationality (ISO 3166-1 alpha-2). JSON: `guest_nationality`. | | | `--min-rating ` | No | minimum guest review rating (0-10). JSON: `min_rating`. | | | `--star-rating ` | No | minimum star rating (1-5). JSON: `min_star_rating`. | | | `--max-star-rating ` | No | maximum star rating (1-5). JSON: `max_star_rating`. | | | `--min-reviews ` | No | minimum number of reviews. JSON: `min_reviews`. | | | `--max-results ` | No | maximum hotels to return per page (default 50). JSON: `max_results`. | | | `--offset ` | No | pagination offset — skip this many hotels at the upstream search (default 0). JSON: `offset`. | | | `--city ` | No | DEPRECATED: use --city-name. | | | `--country ` | No | DEPRECATED: use --country-code. | | | `--lat ` | No | DEPRECATED: use --latitude. | | | `--lng ` | No | DEPRECATED: use --longitude. | | | `--radius ` | No | DEPRECATED: use --radius-km. | | | `--nationality ` | No | DEPRECATED: use --guest-nationality. | | | `--stars ` | No | DEPRECATED: use --star-rating. | | | `--max-stars ` | No | DEPRECATED: use --max-star-rating. | | ## Examples ```bash theme={null} # Paris, 2 adults, 3 nights jinko hotel-search --query "Paris" --checkin 2026-07-15 --checkout 2026-07-18 --adults 2 # By city + country, filtered jinko hotel-search --city-name "Barcelona" --country-code ES \ --checkin 2026-08-01 --checkout 2026-08-05 --adults 2 \ --min-rating 8 --star-rating 4 ``` # jinko lowest-fare Source: https://docs.gojinko.com/cli/lowest-fare Cheapest fares for a fixed route + date — up to ten itineraries, cheapest first The cheapest fares for a fixed route and date. Takes the same inputs as Flight Calendar but for one specific departure date (one-way, or with a return date for round-trip) returns up to ten itineraries sorted cheapest-first. The fixed-date counterpart of Flight Calendar — reach for it when the date is locked and you just want the cheapest options that day. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. ## Usage ```bash theme={null} jinko lowest-fare [options] ``` ## Options | Flag | Required | Description | Default | | --------------------------- | -------- | ------------------------------------------------------------------------------------------------ | ------- | | `--origins ` | Yes | origin IATA airport/city codes. JSON: `origins[]`. | | | `--destinations ` | No | destination IATA airport/city codes. Omit to scan all destinations. JSON: `destinations[]`. | | | `--date ` | Yes | departure date (YYYY-MM-DD). JSON: `departure_dates[0]`. | | | `--return-date ` | No | return date (YYYY-MM-DD) — makes it a round-trip. JSON: `return_dates[0]`. | | | `--cabin-class ` | No | cabin class: economy, premium\_economy, business, first (default: economy). JSON: `cabin_class`. | | | `--direct-only` | No | only direct flights. JSON: `direct_only`. | | | `--from ` | No | DEPRECATED: use --origins. | | | `--to ` | No | DEPRECATED: use --destinations. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | # Overview Source: https://docs.gojinko.com/cli/overview The canonical reference for the Jinko CLI — every command, its flags, and examples. Run flight discovery, live pricing, trips, and booking from your shell. This is the reference for every `jinko` command. Each command page shows its **flags, arguments, and examples**. New here? Start with [Connect via CLI](/connect/cli) for install + first-run setup, then come back for the per-command detail. ## Install ```bash theme={null} npm install -g @gojinko/cli ``` ## Authenticate ```bash theme={null} jinko auth login # OAuth jinko auth login --key jnk_your_key # API key ``` ## Environments The CLI targets **production** by default. Use `--env sandbox` to run against isolated sandbox data, which uses **separate API keys**: | Environment | API base | Flag | | -------------------- | --------------------------------- | --------------- | | Production (default) | `https://api.gojinko.com` | `--env prod` | | Sandbox | `https://api.sandbox.gojinko.com` | `--env sandbox` | ```bash theme={null} jinko config set environment sandbox # make sandbox the default for this machine jinko --env prod find-destination --origins JFK # …or override per-command ``` ## Output Commands print **JSON** by default. Pass `--format table` for a human-readable view. ## Commands by capability Cache-backed search — `find-destination`, `flight-calendar`, `find-dates`, `lowest-fare`, `price-monitoring`. Live pricing + trip building — `flight-search`, `trip`, `select-ancillaries`, `book`, `trip-status`. Live hotel search — `hotel-search`, `hotel-details`. Manage an order — `get-booking`, refund / exchange, `hotel-cancel`. Auth (`auth login` / `logout` / `status`), config (`config set` / `show`), and `schema`. # jinko price-monitoring Source: https://docs.gojinko.com/cli/price-monitoring Monitor price for a specific origin, destination, and dates pair Watch a specific route and date pair over time so an agent can act when the fare drops. Use it for prompts like "alert me when Paris to New York for June 17 to 26 goes under €400". Each response includes the current cheapest cached fare and an offer token you can pass to flight\_search when the user decides to book. Cache-only; never triggers a live call. ## Usage ```bash theme={null} jinko price-monitoring [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | -------- | --------------------------------------------------------------------------------- | -------- | | `--origin ` | Yes | origin IATA code (e.g. PAR for city, CDG for airport). JSON: `origin`. | | | `--destination ` | Yes | destination IATA code (e.g. NYC for city, JFK for airport). JSON: `destination`. | | | `--origin-type ` | No | origin code type: city or airport (default: city). JSON: `origin_type`. | `"city"` | | `--destination-type ` | No | destination code type: city or airport (default: city). JSON: `destination_type`. | `"city"` | | `--departure-date ` | Yes | departure date (YYYY-MM-DD). JSON: `departure_date`. | | | `--return-date ` | No | return date for round-trip (YYYY-MM-DD). JSON: `return_date`. | | | `--adults ` | No | number of adult passengers (default: 1). JSON: `adults`. | | | `--cabin-class ` | No | cabin class: economy, premium\_economy, business, first. JSON: `cabin_class`. | | | `--direct-only` | No | only consider direct flights. JSON: `direct_only`. | | | `--max-price ` | No | upper bound on total fare. JSON: `max_price`. | | | `--include-carriers ` | No | whitelist IATA 2-letter carrier codes (e.g. AF KL). JSON: `include_carriers`. | | | `--exclude-carriers ` | No | blacklist IATA 2-letter carrier codes (e.g. FR U2). JSON: `exclude_carriers`. | | | `--from ` | No | DEPRECATED: use --origin. | | | `--to ` | No | DEPRECATED: use --destination. | | | `--date ` | No | DEPRECATED: use --departure-date. | | | `--return ` | No | DEPRECATED: use --return-date. | | | `--cabin ` | No | DEPRECATED: use --cabin-class. | | | `--passengers ` | No | DEPRECATED: use --adults. | | ## Examples ```bash theme={null} # Plain poll for the cheapest cached PAR → NYC. jinko price-monitoring --origin PAR --destination NYC \ --departure-date 2026-06-17 --return-date 2026-06-26 --format json ``` ```bash theme={null} # Cron entry — poll every 6 hours, alert on a hit. # 0 */6 * * * jinko price-monitoring --origin PAR --destination NYC \ --departure-date 2026-06-17 --return-date 2026-06-26 \ --direct-only --cabin-class economy --max-price 800 \ --format json | jq -e '.status == "ok"' \ && /usr/local/bin/notify-on-price-drop.sh ``` # jinko refund check Source: https://docs.gojinko.com/cli/refund/check Check refund eligibility and estimated amount Check refund eligibility and estimated amount. ## Usage ```bash theme={null} jinko refund check [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | | `--ticket-numbers ` | No | one or more ticket numbers | | ## Examples ```bash theme={null} # Authenticated path jinko refund check --order-id TF-ORDER-123 # Guest path jinko refund check --booking-ref JNK-ABC123 --last-name Doe ``` Read-only, never triggers a refund. Surface the returned `refundable_amount` to the user before calling `commit`. # jinko refund commit Source: https://docs.gojinko.com/cli/refund/commit Initiate a refund for a booked flight Initiate a refund for a booked flight. ## Usage ```bash theme={null} jinko refund commit [options] ``` ## Options | Flag | Required | Description | Default | | ------------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--provider ` | No | override provider hint | | | `--ticket-numbers ` | No | one or more ticket numbers | | ## Examples ```bash theme={null} jinko refund commit --booking-ref JNK-ABC123 --last-name Doe # → { "refund_reference": "REF-xyz789", "status": "pending" } ``` Follow with `jinko refund status` to poll until terminal. # jinko refund status Source: https://docs.gojinko.com/cli/refund/status Check the status of a refund Poll the current status of a previously committed refund. ## Usage ```bash theme={null} jinko refund status [options] ``` ## Options | Flag | Required | Description | Default | | -------------------------- | ------------------------ | ---------------------------------------------------------- | ------- | | `--booking-ref ` | Yes — guest mode | Jinko booking reference (guest auth, requires --last-name) | | | `--last-name ` | Yes — guest mode | Last name of the primary traveler (guest auth) | | | `--order-id ` | Yes — authenticated mode | DevPlatform order ID (authenticated auth) | | | `--refund-reference ` | No | refund reference returned by `refund commit` | | | `--provider ` | No | override provider hint | | ## Examples ```bash theme={null} jinko refund status \ --booking-ref JNK-ABC123 \ --last-name Doe \ --refund-reference REF-xyz789 ``` Terminal states: `succeeded`, `failed`, `cancelled`. Poll every 15-30s until terminal. # jinko schema Source: https://docs.gojinko.com/cli/schema Show request/response schema for a command. List all if no command given. Show request/response schema for a command. List all if no command given. ## Usage ```bash theme={null} jinko schema [options] [command] ``` ### Arguments | Argument | Required | Description | | --------- | -------- | ----------- | | `command` | No | | ## Options *No options.* ## Examples ```bash theme={null} # Dump the current OpenAPI spec (filtered public surface) jinko schema # Pipe into jq, grep for flight endpoints jinko schema | jq '.paths | keys[]' | grep flights ``` Useful for debugging field shapes without leaving the terminal. # jinko select-ancillaries Source: https://docs.gojinko.com/cli/select-ancillaries Select ancillaries (baggage, seats, meals) for a trip item Add baggage, seat selections, or meals to a flight item before checkout. Use it after the trip has a flight item and travelers attached but before `book`, for example when a user requests "two checked bags and a window seat for the outbound leg". Selections use full-replacement semantics — include everything the user wants kept on the trip in a single call. ## Usage ```bash theme={null} jinko select-ancillaries [options] ``` ## Options | Flag | Required | Description | Default | | ---------------- | -------- | --------------------------------------------- | ------- | | `--trip-id ` | Yes | trip ID | | | `--item-id ` | Yes | trip item ID | | | `--select ` | Yes | comma-separated ancillary offer IDs | | | `--pax ` | No | passenger reference (for per-pax ancillaries) | | | `--quantity ` | No | quantity (default: 1) | `"1"` | ## Examples ```bash theme={null} # Preselect a baggage offer before checkout jinko select-ancillaries \ --trip-id 42 \ --item-id 7 \ --select anc_bag_20kg ``` # jinko trip Source: https://docs.gojinko.com/cli/trip Create and manage a trip — add or remove items, set travelers, select ancillaries Assemble and edit a trip before sending it to checkout. Use it to add a flight or hotel offer, set traveler details, swap one item for another, or attach ancillaries like bags and seats. Flights and hotels can sit side by side in the same trip and settle through a single checkout. ## Usage ```bash theme={null} jinko trip [options] ``` ## Options | Flag | Required | Description | Default | | --------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `--trip-id ` | No | existing trip ID (omit to create new) | | | `--trip-item-token ` | No | add a flight item (from flight-search) | | | `--remove-item-id ` | No | remove an existing item by item\_id (from a prior trip response items\[].item\_id). Requires --trip-id. Can be combined with --trip-item-token to swap an item in one call. | | | `--travelers ` | No | travelers JSON array. Required to complete a booking; the first traveler also supplies the booking contact name. | | | `--contact ` | No | contact JSON \{email, phone} — both required. Optional while building the cart, but required before booking. | | ## Examples ```bash theme={null} # Create a trip with an item + travelers in one call jinko trip \ --trip-item-token "$TRIP_ITEM_TOKEN" \ --travelers '[{"first_name":"Jane","last_name":"Doe","date_of_birth":"1990-01-15","gender":"FEMALE","passenger_type":"ADULT","frequent_flyer":{"airline":"LH","number":"992100100"}}]' \ --contact '{"email":"jane@example.com","phone":"+33612345678"}' # Add another item to an existing trip jinko trip --trip-id 42 --trip-item-token "htl_def..." ``` # jinko trip-status Source: https://docs.gojinko.com/cli/trip-status Fetch the full lifecycle state of a trip — items, travelers, quote, fulfillment, and any booking references Inspect the current state of a trip without modifying it. Reach for it when you need to confirm what items are on the trip, verify the travelers attached to a booking, or check whether a checkout has finalized after the user paid. The response covers items, traveler details, quote status, and any booking references that have been issued. ## Usage ```bash theme={null} jinko trip-status [options] ``` ## Options | Flag | Required | Description | Default | | ---------------- | -------- | ----------- | ------- | | `--trip-id ` | Yes | trip ID | | ## Examples ```bash theme={null} # Full trip state: items, travelers, quote, fulfillment, bookings jinko trip-status --trip-id 42 # Poll until fulfillment is terminal while true; do status=$(jinko trip-status --trip-id 42 --format json | jq -r '.fulfillment.status') echo "Status: $status" [[ "$status" == "completed" || "$status" == "failed" ]] && break sleep 5 done ``` # Ancillaries Source: https://docs.gojinko.com/concepts/ancillaries Baggage, seats, meals and other add-ons on a flight — how to read available_ancillaries and select them Ancillaries are the purchasable add-ons on a flight: extra baggage, seat selection, meals, priority boarding, lounge access, and more. They surface on each flight item in a **quoted** cart, and you select them before checkout. ## How to list ancillaries (REST) Ancillaries only exist **after the flight is priced** (the provider — TravelFusion — only emits the catalog at pricing time). They are **not** on the raw `flight_search` result, and you should **not** call `book()` to read them (that mints a checkout URL). Use the dedicated endpoint instead — it runs the price quote transparently and returns the catalog **without generating a checkout URL**: ``` GET /v1/trip/{trip_id}/ancillaries ``` Lifecycle: 1. `flight_search` → live-priced offer 2. `trip` (add item) → flight in the cart 3. `trip` (set travelers) — **required**; ancillaries are priced per passenger 4. **`GET /v1/trip/{trip_id}/ancillaries`** → runs the quote behind the scenes and returns `items[].available_ancillaries[]` 5. `select_ancillaries` → move chosen offers into `selected_ancillaries[]`, updating `total_with_ancillaries` 6. `book()` → checkout ### Response: `ready` vs `pricing` The quote runs upstream and can take a few seconds, so the call is two-state: * **`200` `{ "status": "ready", "items": [...] }`** — the catalog is ready; read `available_ancillaries` off each item. * **`202` `{ "status": "pricing", "retry_after_seconds": 2 }`** + a `Retry-After` header — the quote is still pricing; **poll the same URL** until it returns `200`. A completed quote is **reused while valid** (`expires_at`), so repeat calls return instantly. The response **never** contains a `checkout_url`. The SDK exposes this as `client.getAncillaries(tripId)`. The MCP `trip` tool surfaces the same `available_ancillaries[]` on the quoted trip item inside the widget flow. On the Jinko-hosted checkout page, ancillary selection is not currently exposed — build your own UI against `available_ancillaries` + `select_ancillaries`. ```typescript theme={null} // Set travelers first, then list ancillaries (quote runs transparently). let res = await client.getAncillaries(tripId) while (res.status === 'pricing') { await new Promise(r => setTimeout(r, (res.retry_after_seconds ?? 2) * 1000)) res = await client.getAncillaries(tripId) // poll the same call } const bags = res.items[0].available_ancillaries.filter(a => a.type === 'bag') await client.selectAncillaries({ trip_id: tripId, item_id: res.items[0].item_id, selections: [{ offer_id: bags[0].offer_id }], }) ``` **Two response shapes.** The REST endpoint above returns a **simplified** offer per item — `{ offer_id, type, label, display_label, description, price_per_unit, per_pax, max_quantity }` (where `type` is the lower-cased category, e.g. `bag`, `seat`, `meal`, `assistance`, `cabin_bag_upgrade`, `sports_equipment`, `other`). `label` is the raw provider string; **`display_label`** is a cleaned, human-readable version (HTML entities decoded, provider `&` component-joiners normalized to `, `) — prefer it for display, falling back to `label`. The richer `Ancillary` object documented below (`category`, `scope`, `*_details`, …) is what the **MCP `trip` tool** returns on the quoted trip item. Both carry the same `offer_id` you pass to `select_ancillaries`. ## The cart item ```json theme={null} { "trip_item_token": "...", // ... flight fields ... "available_ancillaries": [ /* Ancillary[] — see below */ ], "selected_ancillaries": [ /* SelectedAncillary[] */ ], "total_with_ancillaries": { "amount": 48500, "currency": "EUR", "decimal_places": 2 } } ``` ## The `Ancillary` object | Field | Type | Notes | | ---------------------- | -------------------- | ------------------------------------------------------- | | `offer_id` | string | Pass this to `select_ancillaries` | | `category` | enum | See the 11 values below | | `label` | string | Human-readable, e.g. `"1 bag · 23kg"` | | `description` | string | Longer description | | `price` | Money | `{ amount, currency, decimal_places }`; absent = free | | `scope` | enum | Who/what it applies to (see below) | | `max_quantity` | integer | Max units selectable | | `mutually_exclusive` | string\[] | `offer_id`s that conflict with this one | | `segment_ref_ids` | string\[] | Segments it applies to | | `journey_ref_id` | string | Journey it applies to | | `applicable_pax_types` | string\[] | e.g. `["ADT"]` | | `provider_metadata` | `map` | Pass-through provider data | | `baggage_details` | object | Present when `category = BAGGAGE` / `CABIN_BAG_UPGRADE` | | `seat_details` | object | Present when `category = SEAT` | | `meal_details` | object | Present when `category = MEAL` | | `assistance_details` | object | Present when `category = SPECIAL_ASSISTANCE` | **`category` (11 values):** `BAGGAGE`, `SEAT`, `MEAL`, `CABIN_BAG_UPGRADE`, `SPORTS_EQUIPMENT`, `PRIORITY_BOARDING`, `SPECIAL_ASSISTANCE`, `INSURANCE`, `LOUNGE`, `FREQUENT_FLYER`, `OTHER`. **`scope` (4 values):** `PER_PAX_PER_SEGMENT`, `PER_PAX_PER_JOURNEY`, `PER_PAX_PER_BOOKING`, `PER_BOOKING`. ### Baggage — `baggage_details` ```json theme={null} { "pieces": 1, "weight_kg": 23, "weight_lb": 50, "dimensions": "158cm" } ``` ### Seat — `seat_details` ```json theme={null} { "flight_number": "AF1234", "seat_type": "STANDARD", "characteristics": ["WINDOW", "EXTRA_LEGROOM"], "available_seats": [ { "seat_number": "12A", "seat_type": "STANDARD", "characteristics": ["WINDOW"], "csp_value": "...", "price": { "amount": 1500, "currency": "EUR", "decimal_places": 2 } } ] } ``` For full seat-map rendering there is also a `SeatMap` shape (`rows[] → seats[]` with `availability` + `features`), but for ancillary purchase you use `seat_details.available_seats`. ### Meal — `meal_details` ```json theme={null} { "meal_code": "VGML", "meal_name": "Vegetarian", "available_meals": [ { "meal_code": "VGML", "meal_name": "Vegetarian", "csp_value": "...", "price": { "amount": 1200, "currency": "EUR", "decimal_places": 2 } } ] } ``` ## Example `available_ancillaries` ```json theme={null} "available_ancillaries": [ { "offer_id": "anc_bag_23", "category": "BAGGAGE", "label": "1 checked bag · 23kg", "price": { "amount": 4500, "currency": "EUR", "decimal_places": 2 }, "scope": "PER_PAX_PER_SEGMENT", "max_quantity": 3, "segment_ref_ids": ["seg_1"], "applicable_pax_types": ["ADT"], "baggage_details": { "pieces": 1, "weight_kg": 23, "weight_lb": 50 } }, { "offer_id": "anc_seat_12A", "category": "SEAT", "label": "Seat 12A (window)", "price": { "amount": 1500, "currency": "EUR", "decimal_places": 2 }, "scope": "PER_PAX_PER_SEGMENT", "mutually_exclusive": ["anc_seat_12B"], "segment_ref_ids": ["seg_1"], "seat_details": { "flight_number": "AF1234", "available_seats": [ { "seat_number": "12A", "seat_type": "STANDARD", "characteristics": ["WINDOW"], "price": { "amount": 1500, "currency": "EUR", "decimal_places": 2 } } ] } }, { "offer_id": "anc_priority", "category": "PRIORITY_BOARDING", "label": "Priority boarding", "price": { "amount": 800, "currency": "EUR", "decimal_places": 2 }, "scope": "PER_PAX_PER_BOOKING" } ] ``` Which ancillaries are returned depends entirely on the airline/provider — many fares return none, LCCs typically return baggage + seats. Always render defensively: any `*_details` block is optional and only present for its category. ## Selecting ancillaries **REST / CLI** — discrete operation: ```bash theme={null} POST /v1/select_ancillaries { "trip_id": "trip_1048576", "item_id": "prod_abc123", "selections": [ { "offer_id": "anc_bag_23", "quantity": 1, "pax_ref_id": "pax_1" } ] } ``` Pass the `offer_id`(s) you read from `available_ancillaries`. Returns the updated `selected_ancillaries[]` + `total_with_ancillaries`. (`@gojinko/cli`: `jinko select-ancillaries`.) **MCP / plugin** — ancillary selection is **not** a standalone tool; it's an action of the umbrella `trip` tool. **mcp-apps** handles it inside the trip/book widget flow. # Errors & troubleshooting Source: https://docs.gojinko.com/concepts/errors HTTP status codes, error envelope, and what to do when things go sideways. Every Jinko endpoint returns errors as JSON in a consistent envelope: ```json theme={null} { "error": { "code": "VALIDATION_FAILED", "message": "departure_date must be in the future", "details": { "field": "departure_date" } } } ``` The SDK converts these to `ApiError` (or its subclasses `AuthError` / `ValidationError`), see [SDK error handling](/connect/sdk#error-handling). ## Status code reference | Status | When | Common causes | What to do | | ----------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **400 Bad Request** | Request shape / values rejected before any business logic | Missing required field, wrong type, malformed JSON | Inspect `error.message`; for the SDK, also catch `ValidationError` | | **401 Unauthorized** | Auth header missing, malformed, or revoked | Forgot `Authorization` / `X-API-Key` header; key rotated; OAuth token expired and refresh failed | Verify credentials. If you're on MCP and pasting a CLI OAuth token, see [OAuth](/authentication/oauth), wrong issuer | | **403 Forbidden** | Authenticated but not allowed | Endpoint requires a higher tier; account inactive | Check the dashboard for account status; reach out if surprised | | **404 Not Found** | Resource doesn't exist OR (on guest endpoints) credentials don't match | `trip_id` typo; `booking_ref` + `last_name` pair doesn't resolve | Verify the ID. On `get_booking` and refund/exchange guest paths, "not found" is intentionally indistinguishable from "wrong last\_name", don't leak existence | | **409 Conflict** | State doesn't allow the operation | Trying to add an item to a fulfilled trip; double-checkout on a quoted trip | Re-fetch state with `getTrip` before retrying | | **422 Unprocessable Entity** | Validated and authorized, but the upstream rejected | Provider says no inventory; price changed beyond tolerance | Re-run discovery / live pricing; the offer is stale | | **429 Too Many Requests** | Rate limit | Free tier is 1,000 requests / 30 days per API key | Wait, or email [dev@gojinko.com](mailto:dev@gojinko.com) for a quota bump | | **500 Internal Server Error** | We blew up | Bug, missing env var, a downstream provider's outage we didn't degrade gracefully | Capture the `X-Request-ID` from your response headers and report, see below | | **502 / 503 / 504** | Upstream provider failure | TravelFusion / Sabre / Nuitée timed out or returned a bad response | Retry once after a small delay; if it persists, the provider is down | ## Reporting issues Every response includes an `X-Request-ID` header (also visible in SDK logs as `X-Request-ID`). Capture it and include in any bug report, we use it to find the exact request server-side in Datadog. ```bash theme={null} curl -i ... | grep -i x-request-id ``` ```typescript theme={null} try { await client.findFlight(...) } catch (err) { if (err instanceof ApiError) { console.error('Request ID:', err.requestId) // include this when reporting } } ``` Email: [dev@gojinko.com](mailto:dev@gojinko.com). ## Common gotchas ### "I get 401 on the MCP endpoint with a token that worked yesterday" If the token came from `jinko auth login`, it's a CLI OAuth token (issuer = Jinko Auth user pool). MCP expects either an API key or an MCP-OAuth JWT (issuer = AuthKit). They look similar but trip the issuer check. Use `jnk_*` for programmatic MCP access. ### "Trip says 'fulfilled' but I never got a confirmation" Confirmation emails go via Resend. If the user's email is correct on the trip's `contact` and the booking status is `completed`, check spam. If the status is stuck on `fulfilling` for more than \~6 hours, the upstream provider is slow, common on TravelFusion when the airline is laggy. ### "trip\_item\_token rejected with 'expired'" `trip_item_token`s have a TTL (\~30 minutes for flights, shorter for some hotel rates). If the user takes a long time on traveler entry, re-run live pricing (`flight_search` / `hotel_search`) before adding to a trip. # LLMs.txt Source: https://docs.gojinko.com/concepts/llms-txt Machine-readable documentation entry points for AI agents. Machine-readable docs are available at: * [llms.txt](https://docs.gojinko.com/llms.txt) * [llms-full.txt](https://docs.gojinko.com/llms-full.txt) # Concepts Source: https://docs.gojinko.com/concepts/overview Trip, quote, fulfillment, the mental model for Jinko's booking flow. Booking with Jinko is a staged workflow. Once you've picked a candidate flight or hotel, every action mutates a server-side **trip** until you ship the user to a Stripe checkout page. This page explains the moving parts. If you just want to ship code, jump to the [Flight booking guide](/guides/flight-booking). ## The pipeline ``` discovery → live pricing → trip → travelers → (ancillaries?) → quote → checkout → user pays → fulfillment ``` Each arrow is a server call. The session state lives on the trip, you never reconstruct it client-side. ## Discovery vs live pricing Two tools play here: * **Discovery** (`find_destination`, `flight_calendar`, `find_dates`, `lowest_fare`) is **cached**. Returns broad, fast, exploratory results. Prices may be 5-30 minutes stale. * **Live pricing** (`flight_search`, `hotel_search`) hits the upstream provider directly. Returns a `trip_item_token` you can add to a trip. You always go discovery → live pricing before adding to a trip. The discovery `offer_token` is not bookable on its own, pass it to `flight_search` (price-check mode) to get a fresh `trip_item_token`. ## Tokens and IDs | Token | Where it comes from | What it does | | ----------------------------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | `offer_token` | Discovery (`find_destination`, `flight_calendar`, `find_dates`, `lowest_fare`) | Identifies a candidate itinerary. Pass to `flight_search` to get pricing. | | `trip_item_token` | Live pricing (`flight_search`, `hotel_search`) | Identifies a price-checked item. Pass to `trip(add_item)`. | | `htl_*` token | `hotel_search` rates | Same role as `trip_item_token` for hotels. Pass to `trip(add_item)`. | | `trip_id` (sometimes `cart_id` in legacy infra) | First call to `trip()` | Identifies the mutable trip for the rest of the flow. | | `quoted_cart_id` / quoted item IDs | Internal to the quote response | Used by `select_ancillaries` to target a specific quoted item. The `quoted_cart_id` is the trip-side echo of `trip_id`. | | `checkout_url` / `session_id` | `book()` response | Stripe-hosted page where the user completes payment. | | `booking_ref` (`JNK-*`) | After fulfillment | Customer-facing booking reference. Use with `get_booking` and refund/exchange tools. | | `pnr` | After fulfillment | Airline-side reservation locator. Surface in confirmation emails. | Tokens are scoped, an `offer_token` from yesterday won't work today. Always go through the pipeline fresh. ## Trip vs cart vs quote * **Trip** is the canonical user-facing name across SDK / CLI / MCP / API docs. All public examples and tool names use it (`trip`, `getTrip`, `trip_id`). * **Cart** is a legacy internal name that surfaces in one place: some server responses still return `cart_id` (numeric, the storage primary key) alongside `trip_id`. They identify the same object — prefer `trip_id` in your code. * A **quote** is the price-locked snapshot of a trip at a point in time. `book()` schedules a quote internally before creating the Stripe session, you don't manipulate quotes directly. ## Multi-domain trips A single trip can hold flight items AND hotel items. They go through one Stripe checkout. To build a multi-domain trip: ```typescript theme={null} // 1. Add a flight await client.trip({ add_item: { trip_item_token: 'offer_abc:fare_xyz' } }) // 2. Add a hotel to the same trip await client.trip({ trip_id: '42', add_item: { trip_item_token: 'htl_def...' } }) // 3. Set travelers (one set, applies to all items) await client.trip({ trip_id: '42', upsert_travelers: { /* ... */ } }) // 4. Single book() schedules a unified checkout await client.book('42') ``` ## Providers The API aggregates multiple upstream providers behind a unified API. As of this writing: * **Flights:** TravelFusion (NDC + LCC), Sabre (GDS). * **Hotels:** Nuitée (LiteAPI). You usually don't need to think about providers, the API picks the cheapest / fastest match. The `provider` field is exposed on responses (and accepted as an override on refund/exchange) for cases where you need to target one explicitly. ## Hosted checkout Jinko owns the payment surface. You never touch credit-card data. Flow: 1. `book()` returns a `checkout_url` pointing at `app.gojinko.com/checkout?sid=`. 2. Send the user there (open in browser, deep-link from a widget, etc.). 3. They pay on Stripe-hosted UI. 4. Stripe webhooks finalize the booking, no client confirm step needed. 5. Poll `getTrip` to watch fulfillment status (`pending → fulfilling → completed | failed`). The user's money never enters your system. You don't need PCI compliance to use Jinko. ## Async fulfillment Booking confirmation isn't always instant, TravelFusion bookings can take up to 72 hours to confirm with the airline. The API handles this with a job queue (River + Postgres). You poll `getTrip` to watch state; the user gets confirmation emails directly from Jinko when their booking lands. For end-to-end mechanics, see the [Flight booking guide](/guides/flight-booking) or the [Flight + Hotel guide](/guides/flight-hotel-booking) for a multi-item trip. # Rate Limits Source: https://docs.gojinko.com/concepts/rate-limits Current Jinko platform rate limits. All access is currently rate-limited to **1,000 requests per 30 days**. If you need higher limits, contact [dev@gojinko.com](mailto:dev@gojinko.com). # CLI Source: https://docs.gojinko.com/connect/cli Install the Jinko CLI and run the booking flow from your shell. The CLI mirrors the booking workflow exposed through MCP and is ideal for shell agents and scripts. ## Install ```bash theme={null} npm install -g @gojinko/cli ``` **`@gojinko/cli` 2.0** targets the canonical `jinko-api` `/v1` surface. Upgrading is **opt-in** — the **1.x** line keeps working unchanged against the legacy routes, which stay served during the transition. Upgrade when you're ready; nothing forces a cutover. ## Authenticate OAuth: ```bash theme={null} jinko auth login ``` API key: ```bash theme={null} jinko auth login --key jnk_your_key export JINKO_API_KEY=jnk_your_key ``` ## First request ```bash theme={null} jinko find-destination --origins JFK jinko flight-calendar --origins JFK --destinations CDG --month 2026-06 jinko flight-search --origin JFK --destination CDG --departure-date 2026-06-15 ``` ## Environments (prod / sandbox) The CLI targets **production** by default. Use `--env sandbox` to run the full flow against the sandbox environment (isolated data, **separate API keys**) before going live: ```bash theme={null} # store your sandbox key under the sandbox profile jinko auth login --env sandbox --key jnk_your_sandbox_key # make sandbox the default for this machine… jinko config set environment sandbox jinko find-destination --origins JFK # → sandbox # …or override per-command jinko --env prod find-destination --origins JFK # → production ``` | Environment | API base | Flag | | -------------------- | --------------------------------- | --------------- | | Production (default) | `https://api.gojinko.com` | `--env prod` | | Sandbox | `https://api.sandbox.gojinko.com` | `--env sandbox` | Prod and sandbox keys are stored separately in `~/.jinko/config.yaml`, so you keep both and switch with `--env`. `JINKO_ENV=sandbox` and the raw `JINKO_API_BASE` override also work. # MCP Source: https://docs.gojinko.com/connect/mcp Connect OAuth-capable MCP clients to Jinko over the remote endpoint. Jinko exposes a remote MCP endpoint with OAuth support. Most modern MCP clients only need the endpoint URL. ## Endpoint ``` https://mcp.builders.gojinko.com/mcp ``` ## Sandbox Test the full flow against the sandbox environment (isolated data) before going to production: ``` https://mcp.builders.sandbox.gojinko.com/mcp ``` Sandbox uses **separate API keys / OAuth** from production — generate a sandbox key from the dashboard. A production token will not authenticate against sandbox (and vice-versa). ## Claude Code ```bash theme={null} claude mcp add --transport http jinko https://mcp.builders.gojinko.com/mcp ``` ## Cursor ```json theme={null} { "mcpServers": { "jinko": { "url": "https://mcp.builders.gojinko.com/mcp" } } } ``` ## API key mode When your client does not support OAuth, attach an `Authorization: Bearer jnk_*` header instead. # TypeScript SDK Source: https://docs.gojinko.com/connect/sdk @gojinko/api-client, typed wrapper around the Jinko REST API. `@gojinko/api-client` is the typed Node.js SDK for the Jinko Public API. It wraps every public endpoint with full TypeScript types, handles authentication (API key or OAuth), and auto-refreshes OAuth tokens when they expire. ## Install ```bash theme={null} npm install @gojinko/api-client ``` Works with Node.js ≥ 20. ESM-only. **`@gojinko/api-client` 2.0** targets the canonical `jinko-api` `/v1` surface. Upgrading is **opt-in** — the existing **1.x** line keeps working unchanged against the legacy routes, which stay served during the transition. Move to 2.0 when you're ready; there's no forced cutover. ## Quick start ```typescript theme={null} import { createJinkoClient } from '@gojinko/api-client' const client = await createJinkoClient({ apiKey: 'jnk_...' }) const { results } = await client.flightCalendar({ origin: 'JFK', destination: 'CDG', departure_date: '2026-06-15', }) ``` ## Authentication `createJinkoClient()` resolves auth in this order: ```typescript theme={null} createJinkoClient({ apiKey: 'jnk_...' }) ``` ```bash theme={null} export JINKO_API_KEY=jnk_... ``` ```typescript theme={null} createJinkoClient() // picks up env ``` The same config file the [CLI](/connect/cli) uses. Run `jinko auth login` to populate it; your scripts pick it up automatically. If none of those yield credentials, `createJinkoClient()` throws `AuthError`. ### OAuth tokens If your config has OAuth tokens (from `jinko auth login` without `--key`), the SDK checks expiry before each request and calls the auth refresh endpoint transparently. Refreshed tokens are written back to `~/.jinko/config.yaml` so long-running scripts don't lose session. You cannot paste an OAuth token directly into `apiKey`, different issuers. Use an API key (`jnk_...`) for programmatic access when you don't want to maintain OAuth state. ## Environments (prod / sandbox) Pass `environment` to target the sandbox (isolated data, **separate API keys**) before going to production: ```typescript theme={null} const client = await createJinkoClient({ environment: 'sandbox', apiKey: 'jnk_your_sandbox_key', }) ``` | `environment` | Base URL | | ------------------ | --------------------------------- | | `'prod'` (default) | `https://api.gojinko.com` | | `'sandbox'` | `https://api.sandbox.gojinko.com` | Resolution precedence: the `environment` option → `JINKO_ENV` → the active environment in `~/.jinko/config.yaml` (shared with the [CLI](/connect/cli) — `jinko config set environment sandbox`) → `prod`. An explicit `baseUrl` or the `JINKO_API_BASE` env var still overrides the mapping (for dev/staging). ## The returned client ```typescript theme={null} interface JinkoClient extends JinkoTools { readonly raw: JinkoRawClient // openapi-fetch client for escape-hatch requests readonly auth: ResolvedAuth // method + token info // ...plus every method in JinkoTools (see Method reference) } ``` * `client.raw`, the underlying [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) client, typed against the full OpenAPI spec. Use this when you need an endpoint not yet exposed via a convenience method. * `client.auth`, resolved credentials (method: `'api_key' | 'oauth'`, plus token info). ## Error handling All errors derive from `ApiError`: ```typescript theme={null} import { ApiError, AuthError, ValidationError } from '@gojinko/api-client' try { await client.flightCalendar({ /* ... */ }) } catch (err) { if (err instanceof AuthError) { // 401, bad or missing credentials } else if (err instanceof ValidationError) { // 400, malformed request } else if (err instanceof ApiError) { // other HTTP errors, err.statusCode is set } } ``` See [Errors & troubleshooting](/concepts/errors) for a full status code reference. ## Observability Every request the SDK emits carries: * `X-Session-ID`, stable per process/CLI session (from `~/.jinko/session.yaml`) * `X-Request-ID`, fresh UUID per request, useful for correlating a failure with Datadog logs * `X-User-ID`, only set on OAuth, from the JWT `sub` claim When reporting a problem, grab the `X-Request-ID` from your SDK logs and we can trace it server-side. ## Method reference The SDK mirrors the [API reference](/api-reference/introduction) 1:1, each method maps to an endpoint. Each endpoint's reference page includes a TypeScript (SDK) tab alongside the CLI + curl samples, so the reference doubles as your SDK docs. Quick map: | SDK method | Purpose | | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | `client.findDestination(req)` | Discover destinations from origin airports | | `client.flightCalendar(req)` | Cached price calendar by route + flexible dates (canonical discovery method) | | `client.flightSearch(req)` | Live pricing: search OR price-check an offer | | `client.hotelSearch(req)` | Live hotel inventory + rates | | `client.trip(req)` | Create / update trip, items, travelers, ancillaries | | `client.selectAncillaries(req)` | Pre-select bags / seats / meals | | `client.getTrip(tripId)` | Inspect trip / quote / fulfillment / bookings | | `client.book(tripId)` | Schedule checkout, get Stripe URL | | `client.getBooking(req)` | Guest lookup by booking\_ref + last\_name | | `client.refundCheck(req)` / `refundCommit(req)` / `refundStatus(req)` | Refund flow | | `client.exchangeShop(req)` / `exchangePrice(req)` / `exchangeCommit(req)` / `exchangeStatus(req)` | Exchange flow | | `client.raw` | Escape hatch, typed `openapi-fetch` client for anything not yet wrapped | Click through any [API endpoint](/api-reference/introduction) for request / response schemas + runnable SDK + CLI + curl examples. ## Next steps End-to-end booking flow in TypeScript, CLI, and MCP. Per-endpoint docs with SDK / CLI / curl samples. API keys, OAuth flows, and when to use each. Status codes, error envelope, and debugging. # Skills Source: https://docs.gojinko.com/connect/skills Prebuilt prompts + workflows that make coding agents better at using Jinko. Skills are packaged prompts + instructions for coding agents (Claude Code, Codex, Openclaw, Cursor). They tell the agent: * Which Jinko tools exist and how they compose * What the canonical booking flow looks like * What NOT to do (e.g., never fabricate traveler data) * Common pitfalls and how to recover Think of a skill as a runbook the agent auto-consults when you ask it to do something travel-related. ## Available skills | Skill | Clients | Source | | ------------------------------------------ | ---------------------------------------------- | -------------------------------------------------------------------------------- | | **`@gojinko/plugin`** (bundle of 6 skills) | Claude Code (as a plugin), Codex (as a plugin) | [npm](https://www.npmjs.com/package/@gojinko/plugin) | | **jinko-flight** (Openclaw) | Openclaw | [clawhub.ai/kevinjinko/jinko-flight](https://clawhub.ai/kevinjinko/jinko-flight) | ### What's inside `@gojinko/plugin` | Skill | What it teaches the agent | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `search-flights` | Discovery: when to use `find_destination`, `flight_calendar`, `flight_search` (cached vs. live, route+dates vs. inspiration) | | `search-hotels` | Live hotel search by destination + dates + occupancy. Filters, room composition, `htl_*` offer tokens for booking | | `book-trip` | Canonical end-to-end flow: search → `trip(add_item)` → travelers → ancillaries → `book`. Multi-domain (flight + hotel) carts | | `manage-booking` | Post-booking: `get_booking`, refund check/commit/status, exchange shop/price/commit/status | | `account` | Auth status, API key handling, common credential pitfalls | | `jinko-cli` | The CLI as an agent surface (mirrors the MCP tools as `jinko` shell commands) | ## Install (Claude Code) ```bash theme={null} # The plugin bundles the skill + sample scripts claude plugin add @gojinko/plugin ``` Claude Code picks up the skill automatically. First time you ask it a travel question it'll propose the Jinko flow. ## Install (Codex) ```bash theme={null} codex plugin add @gojinko/plugin ``` The plugin ships with both Claude and Codex skill manifests so you install it once. ## Install (Openclaw) Via the Clawhub UI: [clawhub.ai/kevinjinko/jinko-flight](https://clawhub.ai/kevinjinko/jinko-flight) → **Install**. The skill is bundled with a curated prompt. ## When to use a skill | Situation | Skill helps? | | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | You want an agent to book a trip via CLI without hand-holding | Yes, the skill knows the 8-step flow | | You're building your own MCP agent and want Jinko-specific prompting | Yes, import the skill's markdown as your system prompt | | You're calling the SDK directly from your own code | No, use the [SDK docs](/connect/sdk) and [Flight booking guide](/guides/flight-booking) | | You want a chat agent to just "find me a flight" | No, MCP OAuth is enough, no skill needed | Skills are for **coding agents**. Consumer-facing conversational agents (Claude Desktop, ChatGPT) work great with just the MCP endpoint + OAuth. ## Writing your own The existing skills are plain markdown with a small YAML preamble. Copy one and edit: * **Claude Code plugins**: [plugin repo](https://github.com/jinkoso/jinko-dev-tools/tree/main/packages/plugin/skills) * **Codex plugins**: same repo, parallel folder Make a PR if you write a skill for a client we don't yet support, we'll list it here. ## Want more? Jinko Discord has a `#skills` channel where the community shares custom skills and prompts. Email [dev@gojinko.com](mailto:dev@gojinko.com) for the invite. # Flight booking Source: https://docs.gojinko.com/guides/flight-booking Discover, price, build, and book a real flight, with side-by-side examples for SDK, CLI, and MCP. This guide walks you through booking a real flight from start to finish. The same flow works regardless of interface, so each step shows three variants: SDK, CLI, and MCP. The one-line version of the flow: ``` discovery → flight_search → trip(add_item + travelers) → book → user pays → get_trip ``` ## Prerequisites * A Jinko account and an API key (`jnk_...`). [Get one](https://gojinko.com/dashboard/keys). * For the SDK path: Node.js 20 or later, then `npm install @gojinko/api-client`. * For the CLI path: `npm install -g @gojinko/cli && jinko auth login --key jnk_...`. * For the MCP path: any MCP client connected to `https://mcp.builders.gojinko.com/mcp`. ## 1) Discover flights Start with discovery. It is cached, fast, and broad. ```typescript theme={null} import { createJinkoClient } from '@gojinko/api-client' const client = await createJinkoClient({ apiKey: process.env.JINKO_API_KEY }) const result = await client.findFlight({ origin: 'JFK', destination: 'CDG', trip_type: 'roundtrip', departure_dates: ['2026-06-15'], return_dates: ['2026-06-22'], }) const candidate = result.results[0] console.log(candidate.offer_token, candidate.price) ``` ```bash theme={null} jinko flight-calendar \ --origins JFK --destinations CDG \ --month 2026-06 \ --format json \ | jq '.results[0]' ``` Copy the `offer_token` from the top result. Ask the agent: > "Find me a roundtrip from JFK to CDG leaving June 15, 2026, returning June 22." The agent calls `flight_calendar` and shows you candidates. Pick one. ## 2) Live pricing Discovery returns cached prices. Before booking, confirm them with `flight_search`. `flight_search` is a **flat** request: `origin`, `destination`, and `departure_date` are required (`return_date` for round-trips). To re-price a specific candidate from discovery, also pass its `offer_token` — but the route and dates are still required alongside it. The response is an `offers[]` list, and each offer carries a `fares[]` array. **A fare's `trip_item_token` is ready to drop straight into a trip — no assembly required.** ```typescript theme={null} const priced = await client.flightSearch({ origin: 'JFK', destination: 'CDG', departure_date: '2026-06-15', return_date: '2026-06-22', trip_type: 'roundtrip', offer_token: candidate.offer_token, // optional: re-price the discovered offer }) const offer = priced.offers[0] const tripItemToken = offer.fares[0].trip_item_token ``` ```bash theme={null} jinko flight-search \ --origin JFK --destination CDG \ --departure-date 2026-06-15 --return-date 2026-06-22 \ --offer-token offer_abc... \ --format json | jq -r '.offers[0].fares[0].trip_item_token' ``` The printed `trip_item_token` is ready to use as-is. > "Yes, book that one." The agent calls `flight_search` and surfaces the available fares (economy, premium, business). Pick one. If the response status is `flight_unavailable`, the flight sold out between discovery and now, and the `alternatives[]` field has replacements. Loop back to discovery or present them to the user. ## 3) Build the trip Now you have a live `trip_item_token`. Add it to a trip AND set travelers in one call: ```typescript theme={null} const trip = await client.trip({ add_item: { trip_item_token: tripItemToken }, upsert_travelers: { travelers: [{ first_name: 'Jane', last_name: 'Doe', date_of_birth: '1990-01-15', gender: 'FEMALE', passenger_type: 'ADULT', }], contact: { email: 'jane@example.com', phone: '+33612345678', }, }, }) const tripId = trip.trip_id ``` ```bash theme={null} jinko trip \ --trip-item-token "$TRIP_ITEM_TOKEN" \ --travelers '[{"first_name":"Jane","last_name":"Doe","date_of_birth":"1990-01-15","gender":"FEMALE","passenger_type":"ADULT"}]' \ --contact '{"email":"jane@example.com","phone":"+33612345678"}' \ --format json | jq '.trip_id' ``` The agent collects traveler info (names, dates of birth, passport) from you and calls `trip(add_item + upsert_travelers)`. Never let an agent fabricate traveler data. Names, dates of birth, and passport numbers must match the actual passenger's travel documents. Airlines enforce this. ## 4) Quote and select ancillaries (optional) If you want to preselect bags, seats, or meals before checkout, list what's available with `getAncillaries` — it surfaces the ancillaries **without** generating a checkout URL — then pre-select. (Make sure travelers are set first; ancillaries are priced per passenger.) ```typescript theme={null} // List ancillaries — runs a price quote behind the scenes, no checkout URL. let ancillaries = await client.getAncillaries(tripId) // The quote may still be pricing; poll until it's ready. while (ancillaries.status === 'pricing') { await new Promise(r => setTimeout(r, (ancillaries.retry_after_seconds ?? 2) * 1000)) ancillaries = await client.getAncillaries(tripId) } // Pick an ancillary offer const item = ancillaries.items[0] const bagOffer = item.available_ancillaries.find(a => a.type === 'bag') await client.selectAncillaries({ trip_id: tripId, item_id: item.item_id, selections: [{ offer_id: bagOffer.offer_id }], }) ``` You don't have to pre-select. Your user can pick on the Stripe checkout page. Skip this step if you want the simplest flow. ```bash theme={null} jinko select-ancillaries --trip-id "$TRIP_ID" --item-id "$ITEM_ID" --select "$BAG_OFFER_ID" ``` Ancillary selection happens inside the `book` widget. The user clicks through the add-ons UI there. ## 5) Checkout Create the Stripe checkout session: ```typescript theme={null} const { checkout_url } = await client.book(tripId) console.log('Open in browser:', checkout_url) ``` ```bash theme={null} jinko book --trip-id "$TRIP_ID" # → { "checkout_url": "https://app.gojinko.com/checkout?sid=...", ... } ``` The agent automatically opens the checkout in a browser window (`openLink` via MCP Apps). The `checkout_url` points at `app.gojinko.com/checkout`, a Stripe-hosted page Jinko owns. On **REST / CLI / SDK**, `book` is **synchronous**: it schedules the quote, polls until it's ready, and returns the full checkout envelope in one call — `{ session_id, checkout_url, status: "ready", total_amount, items }`. (On **MCP**, the booking widget drives this interactively instead of returning the envelope.) Either way, fulfillment still happens asynchronously *after* the user pays — see steps 7–8. ## 6) User pays Send the user to `checkout_url`. They: 1. Confirm the itinerary. 2. Pick ancillaries (if not pre-selected). 3. Enter payment. 4. Stripe holds the authorization. ## 7) Fulfillment is automatic Once the user pays, Stripe webhooks trigger fulfillment on the API. No client-side confirm step is needed. Fulfillment states (`get_trip → fulfillment.status`): | State | Meaning | | ------------ | --------------------------------------------------------- | | `pending` | Payment cleared, booking not yet attempted | | `fulfilling` | Calling the airline or provider (takes seconds to hours) | | `completed` | Booking confirmed, `pnr` and `booking_ref` populated | | `failed` | Provider rejected (rare). Refund is issued automatically. | ## 8) Watch the booking land Poll `get_trip` until `fulfillment.status` is terminal: ```typescript theme={null} async function waitForBooking(client, tripId: string) { while (true) { const trip = await client.getTrip(tripId) if (trip.fulfillment?.status === 'completed') { console.log('Booked! Ref:', trip.bookings[0].booking_ref) return trip } if (trip.fulfillment?.status === 'failed') { throw new Error('Booking failed, refund in progress') } await new Promise(r => setTimeout(r, 5000)) } } ``` ```bash theme={null} while true; do status=$(jinko trip-status --trip-id "$TRIP_ID" --format json | jq -r '.fulfillment.status') echo "Status: $status" [[ "$status" == "completed" || "$status" == "failed" ]] && break sleep 5 done ``` The agent can poll with `get_trip`, or the user receives a confirmation email directly from Jinko when the booking lands. ## What's next? * **Add a hotel to the trip**: see the [Flight + Hotel guide](/guides/flight-hotel-booking) for one trip with two items. * **Hotel-only booking**: see the [Hotel booking guide](/guides/hotel-booking). * **Refund a booking**: [Refund flow](/tools/flight-refund), `refund-check` then `refund-commit` then `refund-status`. * **Exchange dates**: [Exchange flow](/tools/flight-exchange), a four-step variant of the booking flow. * **Troubleshooting**: [Errors](/concepts/errors) has the full status-code reference. # Flight + Hotel booking Source: https://docs.gojinko.com/guides/flight-hotel-booking One trip, two items, one Stripe checkout. Add a flight and a hotel to the same trip and book them together. Most real journeys involve more than one item. Jinko's `trip` is a single booking unit: you can put a flight and a hotel into the same trip, set the travelers once, and check out once. The user pays a single Stripe charge and receives a single confirmation with a single Jinko booking reference covering both bookings. This guide builds a Paris weekend (a flight from JFK to CDG and a hotel in Paris) end to end with side-by-side examples for SDK, CLI, and MCP. The one-line version of the flow: ``` flight discovery → flight_search → hotel_search → trip(add_item flight + travelers) → trip(add_item hotel) → book → user pays → get_trip ``` ## Prerequisites * A Jinko account and an API key (`jnk_...`). [Get one](https://gojinko.com/dashboard/keys). * For the SDK path: Node.js 20 or later, then `npm install @gojinko/api-client`. * For the CLI path: `npm install -g @gojinko/cli && jinko auth login --key jnk_...`. * For the MCP path: any MCP client connected to `https://mcp.builders.gojinko.com/mcp`. ## 1) Find the flight Discover flights for the route and dates, then confirm pricing on the candidate the user picks. This is the same first two steps as the [Flight booking guide](/guides/flight-booking), so we keep it short. ```typescript theme={null} import { createJinkoClient } from '@gojinko/api-client' const client = await createJinkoClient({ apiKey: process.env.JINKO_API_KEY }) const flightCandidates = await client.findFlight({ origin: 'JFK', destination: 'CDG', trip_type: 'roundtrip', departure_dates: ['2026-06-15'], return_dates: ['2026-06-22'], }) // flight_search is flat: origin/destination/departure_date are required; // offer_token (optional) re-prices the discovered candidate. The returned // fare's trip_item_token is ready to add to a trip as-is. const priced = await client.flightSearch({ origin: 'JFK', destination: 'CDG', departure_date: '2026-06-15', return_date: '2026-06-22', trip_type: 'roundtrip', offer_token: flightCandidates.results[0].offer_token, }) const flightToken = priced.offers[0].fares[0].trip_item_token ``` ```bash theme={null} FLIGHT_OFFER=$(jinko flight-calendar --origins JFK --destinations CDG \ --month 2026-06 --format json | jq -r '.results[0].offer_token') FLIGHT_TOKEN=$(jinko flight-search \ --origin JFK --destination CDG \ --departure-date 2026-06-15 --return-date 2026-06-22 \ --offer-token "$FLIGHT_OFFER" \ --format json | jq -r '.offers[0].fares[0].trip_item_token') ``` > "Find me a roundtrip from JFK to CDG, leaving June 15, returning June 22." Pick a candidate. The agent calls `flight_search(price_check)` to confirm the live price and surfaces fare options. Pick one. The agent now has a flight `trip_item_token` ready to drop into a trip. ## 2) Find the hotel Search hotels at the destination for the same dates. Hotel rates are already live offers, no separate price-check step is needed. ```typescript theme={null} const hotels = await client.hotelSearch({ destination: { query: 'Paris' }, checkin: '2026-06-15', checkout: '2026-06-22', adults: 1, }) const hotelToken = hotels.hotels[0].rooms[0].rates[0].offer_id // htl_* ``` ```bash theme={null} HOTEL_TOKEN=$(jinko hotel-search \ --destination '{"query":"Paris"}' \ --checkin 2026-06-15 --checkout 2026-06-22 \ --adults 1 \ --format json | jq -r '.hotels[0].rooms[0].rates[0].offer_id') ``` > "And find me a 4-star hotel near the Louvre for the same dates." The agent calls `hotel_search` and shows you matching hotels and rates. Pick one. The agent now has a hotel `htl_*` offer ID ready for the next step. ## 3) Build the trip with both items Now the key step. Add the flight to a new trip and set travelers in the same call. Then add the hotel to the same trip with a second `trip(add_item)` call. Both items now live on the same trip and will check out together. ```typescript theme={null} // Create the trip with the flight + travelers in one call. const trip = await client.trip({ add_item: { trip_item_token: flightToken }, upsert_travelers: { travelers: [{ first_name: 'Jane', last_name: 'Doe', date_of_birth: '1990-01-15', gender: 'FEMALE', passenger_type: 'ADULT', }], contact: { email: 'jane@example.com', phone: '+33612345678', }, }, }) const tripId = trip.trip_id // Append the hotel to the same trip. await client.trip({ trip_id: tripId, add_item: { trip_item_token: hotelToken }, }) ``` ```bash theme={null} # Create the trip with the flight + travelers in one call. TRIP_ID=$(jinko trip \ --trip-item-token "$FLIGHT_TOKEN" \ --travelers '[{"first_name":"Jane","last_name":"Doe","date_of_birth":"1990-01-15","gender":"FEMALE","passenger_type":"ADULT"}]' \ --contact '{"email":"jane@example.com","phone":"+33612345678"}' \ --format json | jq -r '.trip_id') # Append the hotel to the same trip. jinko trip --trip-id "$TRIP_ID" --trip-item-token "$HOTEL_TOKEN" ``` The agent calls `trip(add_item + upsert_travelers)` with the flight token, then a second `trip(add_item)` with the hotel offer ID and the same `trip_id`. From the user's point of view, this is one continuous conversation. Travelers belong to the trip, not to each item. Set them once with `upsert_travelers` and they apply to every flight and hotel on the trip. The trip response now contains two `items[]`: the flight and the hotel. The total price is the sum of both, in the same currency. ## 4) Checkout Call `book` once. You get one Stripe `checkout_url` covering both items. ```typescript theme={null} const { checkout_url } = await client.book(tripId) console.log('Open in browser:', checkout_url) ``` ```bash theme={null} jinko book --trip-id "$TRIP_ID" # → { "checkout_url": "https://app.gojinko.com/checkout?sid=...", ... } ``` The agent calls `book` and opens the checkout in a browser window. The Stripe page shows both items, the combined total, and a single payment. ## 5) User pays The user opens `checkout_url`, sees the flight and the hotel side by side with one total, enters payment once, and Stripe holds the authorization. ## 6) Fulfillment Stripe webhooks trigger fulfillment for both items. They book in parallel and the trip is `completed` once both providers confirm. | State | Meaning | | ------------ | ------------------------------------------------------ | | `pending` | Payment cleared, neither item booked yet | | `fulfilling` | At least one item is still being booked | | `completed` | Both items confirmed, `booking_ref` populated for each | | `failed` | A provider rejected. Refund covers the full amount. | If only one of the two providers fails, Jinko rolls back the other booking and refunds the full charge. You get a single, atomic outcome: both succeed or neither does. ## 7) Watch the booking land Poll `get_trip` until `fulfillment.status` is terminal. The `bookings[]` array will contain entries for both the flight and the hotel. ```typescript theme={null} const trip = await client.getTrip(tripId) if (trip.fulfillment?.status === 'completed') { for (const booking of trip.bookings) { console.log(booking.type, booking.booking_ref) } } ``` ```bash theme={null} jinko trip-status --trip-id "$TRIP_ID" --format json | jq '.bookings' ``` The agent calls `get_trip` and reports both confirmation references back to the user. Jinko also sends a single confirmation email covering the full trip. ## What's next? * **Just a flight**: see the [Flight booking guide](/guides/flight-booking) for the full eight-step flow. * **Just a hotel**: see the [Hotel booking guide](/guides/hotel-booking). * **Add ancillaries to the flight**: see [step 4 of the flight guide](/guides/flight-booking#4-quote-and-select-ancillaries-optional). * **Refund or exchange the flight after booking**: [flight\_refund](/tools/flight-refund) and [flight\_exchange](/tools/flight-exchange). * **Troubleshooting**: [Errors](/concepts/errors) has the full status-code reference. # Hotel booking Source: https://docs.gojinko.com/guides/hotel-booking Discover, build, and book a real hotel stay, with side-by-side examples for SDK, CLI, and MCP. This guide walks you through booking a hotel from start to finish. Hotels skip the separate price-check step you see in flight booking: each rate returned by `hotel_search` is already a live offer with an `htl_*` token you can drop straight into a trip. The one-line version of the flow: ``` hotel_search → trip(add_item + travelers) → book → user pays → get_trip ``` ## Prerequisites * A Jinko account and an API key (`jnk_...`). [Get one](https://gojinko.com/dashboard/keys). * For the SDK path: Node.js 20 or later, then `npm install @gojinko/api-client`. * For the CLI path: `npm install -g @gojinko/cli && jinko auth login --key jnk_...`. * For the MCP path: any MCP client connected to `https://mcp.builders.gojinko.com/mcp`. ## 1) Search hotels Search live inventory for the destination, dates, and occupancy. Hotel rates returned here are already priced and bookable. ```typescript theme={null} import { createJinkoClient } from '@gojinko/api-client' const client = await createJinkoClient({ apiKey: process.env.JINKO_API_KEY }) const result = await client.hotelSearch({ destination: { query: 'Paris' }, checkin: '2026-07-15', checkout: '2026-07-18', adults: 2, }) const hotel = result.hotels[0] const rate = hotel.rooms[0].rates[0] console.log(hotel.name, rate.offer_id, rate.total_amount) ``` ```bash theme={null} jinko hotel-search \ --destination '{"query":"Paris"}' \ --checkin 2026-07-15 --checkout 2026-07-18 \ --adults 2 \ --format json \ | jq '.hotels[0].rooms[0].rates[0]' ``` Copy the `offer_id` (starts with `htl_`). Ask the agent: > "Find a 4-star hotel in Paris from July 15 to July 18 for 2 adults." The agent calls `hotel_search` and shows you results. Pick a hotel and a rate. The `destination` field accepts five shapes (free-text query, city plus country code, lat/lng with optional radius, place ID, or a list of hotel IDs). Use whichever matches what you have. ## 2) Build the trip Add the chosen rate to a trip and set travelers in one call. The hotel `offer_id` (the `htl_*` token) goes into `trip(add_item)` exactly the same way a flight `trip_item_token` does. ```typescript theme={null} const trip = await client.trip({ add_item: { trip_item_token: rate.offer_id }, upsert_travelers: { travelers: [{ first_name: 'Jane', last_name: 'Doe', date_of_birth: '1990-01-15', gender: 'FEMALE', passenger_type: 'ADULT', }], contact: { email: 'jane@example.com', phone: '+33612345678', }, }, }) const tripId = trip.trip_id ``` ```bash theme={null} jinko trip \ --trip-item-token "$HOTEL_OFFER_ID" \ --travelers '[{"first_name":"Jane","last_name":"Doe","date_of_birth":"1990-01-15","gender":"FEMALE","passenger_type":"ADULT"}]' \ --contact '{"email":"jane@example.com","phone":"+33612345678"}' \ --format json | jq '.trip_id' ``` The agent collects traveler info (names, dates of birth, contact) from you and calls `trip(add_item + upsert_travelers)`. Hotels enforce name matching at check-in. Never let an agent fabricate traveler data. Use the actual guest's legal name as it appears on a government ID. ## 3) Checkout Create the Stripe checkout session: ```typescript theme={null} const { checkout_url } = await client.book(tripId) console.log('Open in browser:', checkout_url) ``` ```bash theme={null} jinko book --trip-id "$TRIP_ID" # → { "checkout_url": "https://app.gojinko.com/checkout?sid=...", ... } ``` The agent automatically opens the checkout in a browser window (`openLink` via MCP Apps). The `checkout_url` points at `app.gojinko.com/checkout`, a Stripe-hosted page Jinko owns. ## 4) User pays Send the user to `checkout_url`. They: 1. Confirm the hotel, dates, and room. 2. Enter payment. 3. Stripe holds the authorization. ## 5) Fulfillment is automatic Once the user pays, Stripe webhooks trigger fulfillment on the API. No client-side confirm step is needed. Fulfillment states (`get_trip → fulfillment.status`): | State | Meaning | | ------------ | --------------------------------------------------------- | | `pending` | Payment cleared, booking not yet attempted | | `fulfilling` | Calling the hotel provider (typically seconds) | | `completed` | Reservation confirmed, `booking_ref` populated | | `failed` | Provider rejected (rare). Refund is issued automatically. | ## 6) Watch the booking land Poll `get_trip` until `fulfillment.status` is terminal: ```typescript theme={null} async function waitForBooking(client, tripId: string) { while (true) { const trip = await client.getTrip(tripId) if (trip.fulfillment?.status === 'completed') { console.log('Booked! Ref:', trip.bookings[0].booking_ref) return trip } if (trip.fulfillment?.status === 'failed') { throw new Error('Booking failed, refund in progress') } await new Promise(r => setTimeout(r, 5000)) } } ``` ```bash theme={null} while true; do status=$(jinko trip-status --trip-id "$TRIP_ID" --format json | jq -r '.fulfillment.status') echo "Status: $status" [[ "$status" == "completed" || "$status" == "failed" ]] && break sleep 5 done ``` The agent can poll with `get_trip`, or the user receives a confirmation email directly from Jinko when the booking lands. ## What's next? * **Add a flight to the trip**: see the [Flight + Hotel guide](/guides/flight-hotel-booking) for one trip with two items and one Stripe checkout. * **Flight-only booking**: see the [Flight booking guide](/guides/flight-booking). * **Search by location, chain, or amenities**: the [hotel\_search tool reference](/tools/hotel-search) covers every filter (star rating, hotel type, chain, facilities, geo radius). * **Lookup a booking after the fact**: [get\_booking](/tools/get-booking) finds a booking by reference and last name without needing a login. * **Troubleshooting**: [Errors](/concepts/errors) has the full status-code reference. # Webhooks Source: https://docs.gojinko.com/guides/webhooks Get notified when bookings complete or fail — register a callback, verify the signature, handle the event. Webhooks push booking lifecycle events to your server so you don't have to poll. Register an HTTPS endpoint and Jinko sends a signed `POST` the moment a booking is confirmed or fails. The one-line version: ``` register endpoint → Jinko POSTs a signed event → you verify X-Jinko-Signature → you act ``` ## Prerequisites * A Jinko account and an API key (`jnk_...`). [Get one](https://gojinko.com/dashboard/keys). * An HTTPS endpoint that can receive a `POST` (must be `https://` and publicly reachable). ## 1) Register an endpoint Go to [Dashboard → Webhooks](https://gojinko.com/dashboard/webhooks), click **Add webhook**, paste your URL, pick the events, and **Create**. Copy the signing secret shown once — you'll need it to verify deliveries. ```bash theme={null} curl -X POST https://api.gojinko.com/v1/webhooks \ -H "X-API-Key: $JINKO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-app.com/webhooks/jinko", "events": ["booking.completed", "booking.failed"] }' ``` The response contains the signing `secret` **once** — store it securely: ```json theme={null} { "id": 42, "url": "https://your-app.com/webhooks/jinko", "events": ["booking.completed", "booking.failed"], "secret": "whsec_3f9a…", "status": "active", "created_at": "2026-06-02T08:00:00Z" } ``` ## 2) Events | Event | When it fires | | ------------------- | --------------------------------------------------------- | | `booking.completed` | The booking is fulfilled **and** paid (payment captured). | | `booking.failed` | The booking could not be fulfilled. | More event types will be added over time — treat the `event` field as an open enum and ignore events you don't handle. ## 3) Payload Deliveries are intentionally **thin** — identifiers only, no traveler PII. Fetch full detail with [`get_booking`](/api/get-booking) using the `booking_ref`. ```json theme={null} { "event": "booking.completed", "booking_ref": "JNK-A7B3X9", "status": "confirmed", "occurred_at": "2026-06-02T08:00:00Z", "event_id": "evt_01HX…", "livemode": true } ``` Each request also carries these headers: | Header | Purpose | | --------------------- | ------------------------------------------------------------- | | `X-Jinko-Signature` | `sha256=` HMAC of the request (see below). | | `X-Jinko-Timestamp` | Unix seconds; part of the signed payload (replay protection). | | `X-Jinko-Event-Id` | Stable id for the business event — use it to dedupe. | | `X-Jinko-Delivery-Id` | Id of this specific delivery attempt. | ## 4) Verify the signature Compute `HMAC-SHA256(secret, ".")` and compare it, in constant time, to the hex in `X-Jinko-Signature` (after the `sha256=` prefix). **Use the raw request body** — parsing and re-serializing the JSON will change the bytes and break the check. ```javascript theme={null} import crypto from 'node:crypto'; // rawBody: the exact bytes Jinko sent (Buffer/string), NOT re-serialized JSON. function verifyJinkoWebhook(rawBody, headers, secret) { const ts = headers['x-jinko-timestamp']; const sig = headers['x-jinko-signature']; // "sha256=" const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex'); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig)); } ``` ```python theme={null} import hashlib import hmac def verify_jinko_webhook(raw_body: bytes, headers: dict, secret: str) -> bool: ts = headers["X-Jinko-Timestamp"] sig = headers["X-Jinko-Signature"] # "sha256=" signed = f"{ts}.".encode() + raw_body expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, sig) ``` Reject the request if the signature doesn't match, or if `X-Jinko-Timestamp` is older than your tolerance (e.g. 5 minutes) to guard against replays. Respond `2xx` once you've accepted the event. ## 5) Retries & idempotency * A non-`2xx` response (or a timeout) is **retried** with exponential backoff — up to 8 attempts over several hours. * Retries mean you may receive the **same event more than once**. Deduplicate on `X-Jinko-Event-Id` (a given business event always carries the same id). * Return `2xx` as soon as you've durably recorded the event; do slow work asynchronously so you don't trip the delivery timeout. ## 6) Test it Use **Send test** in the dashboard, or: ```bash theme={null} curl -X POST https://api.gojinko.com/v1/webhooks/42/test \ -H "X-API-Key: $JINKO_API_KEY" ``` This delivers a sample event with `"livemode": false` and `booking_ref: "JNK-TEST00"`, so you can confirm your signature handling end-to-end without a real booking. # Jinko Platform Source: https://docs.gojinko.com/introduction Build agents that discover, price, book, and manage travel products. Jinko gives any agent the ability to discover, price, book, and manage travel products. One backend for flights and hotels, one trip that holds them together, one Stripe checkout to close the sale. Grab your API key and ask your coding agents to build. Connect a client and run your first search in under two minutes. ## What you can build Jinko is the travel layer for products that already have a user, a conversation, or a checkout. A few shapes we see in production: Book a flight, a hotel, or a full trip without leaving the thread. The agent collects travelers, surfaces prices, and hands the user a checkout link. Concierge over the phone. The voice agent searches, prices, and confirms a trip while the caller is on the line, then sends a booking link by SMS. Sell flights and hotels under your own brand. Same trip, same checkout, your UI on top of Jinko inventory. Help employees self-book within policy. The copilot searches, picks compliant fares, and books in one transaction. [View more use cases →](https://gojinko.com/usecases/) ## Three ways to connect Jinko ships the same booking surface through three products. Pick the one that fits where your code already lives. For agentic clients (Claude, ChatGPT, Cursor, voice agents, custom MCP hosts). One URL, OAuth or bearer auth, and your agent gains the full tool surface. For backend services, custom apps, and travel websites. REST over HTTPS with a typed OpenAPI spec and a TypeScript SDK. For shell agents, scripts, and CI runners. The same booking flow, end to end from a terminal. All three products talk to the same backend, see the same inventory, and share the same `trip_id`. You can start a trip from a CLI script, hand it off to a website checkout, and inspect it from an MCP client. Same trip, every time. ## The trip, one booking unit for the whole journey A real journey is rarely one item. A trip from JFK to Paris is usually a flight, plus a hotel, plus bags, plus a chosen seat. The **trip** is the object that holds all of that together. Think of the trip as a single booking unit. You add items to it (flights and hotels today, more on the way), set the travelers once, and check out once. The user pays a single Stripe charge and receives a single confirmation with a single Jinko booking reference. A trip moves through four stages: 1. **Add items.** Call `trip(add_item)` with a flight `trip_item_token` from `flight_search`, a hotel `offer_id` (the `htl_*` token) from `hotel_search`, or both. Each call appends to the same trip. 2. **Set travelers.** Call `trip(upsert_travelers)` once per trip. Names, dates of birth, and contact info travel with every item on the trip. 3. **Book.** Call `book` to schedule checkout. You get back a Stripe `checkout_url`. 4. **Pay and fulfill.** The user pays on the Stripe page. Webhooks finalize the booking automatically. Poll `get_trip` to watch fulfillment land. The same `trip_id` works whether you drive it from MCP, the API, or the CLI. Start somewhere, finish somewhere else. For a step-by-step example with two items in the same trip, see the [Flight + Hotel guide](/guides/flight-hotel-booking). ## Where to go next Connect a client and book your first trip. End-to-end walkthroughs for flight, hotel, and combined bookings. Every MCP tool, parameters, and what the model sees. REST endpoints, request and response shapes, and the OpenAPI spec. # How to Connect Source: https://docs.gojinko.com/quickstart Connect your AI agent to Jinko in under 2 minutes. Connect your AI agent to Jinko in under 2 minutes. One URL and your agent can search flights and hotels, compare prices, and book travel — flights and hotels share the same trip. **Production vs sandbox.** The URLs below are **production**. To test the full flow without touching prod data, use the **sandbox** environment — it uses **separate API keys** ([Sandbox keys](/authentication/api-keys#sandbox-keys)): | Surface | Production | Sandbox | | ---------- | -------------------------------------- | ---------------------------------------------- | | MCP | `https://mcp.builders.gojinko.com/mcp` | `https://mcp.builders.sandbox.gojinko.com/mcp` | | REST / SDK | `https://api.gojinko.com` | `https://api.sandbox.gojinko.com` | | CLI | default | add `--env sandbox` | ## Connect via MCP OAuth MCP clients that support OAuth with Dynamic Client Registration (DCR) authenticate automatically. Just provide the endpoint, the client handles discovery, registration, and the browser-based sign-in flow (OAuth 2.1 with PKCE). No configuration needed. Supported clients: **Claude Desktop**, **Claude Code**, **ChatGPT**, **Cursor**, and any MCP client with OAuth/DCR support. ### Claude Desktop / Claude Web Go to **Settings > Connectors > Add custom connector**: | Field | Value | | ----- | -------------------------------------- | | Name | `Jinko Travel` | | URL | `https://mcp.builders.gojinko.com/mcp` | Leave OAuth fields empty, Claude handles the auth flow automatically. You'll sign in with your Jinko account on first use. ### Claude Code ```bash theme={null} claude mcp add --transport http jinko https://mcp.builders.gojinko.com/mcp ``` OAuth will open a browser window for sign-in on first use. ### Cursor Go to **Settings > MCP Servers > Add Server**: ```json theme={null} { "mcpServers": { "jinko": { "url": "https://mcp.builders.gojinko.com/mcp" } } } ``` ### CLI The CLI uses its own OAuth flow (device authorization via Jinko Auth), this is separate from MCP OAuth. ```bash theme={null} npm install -g @gojinko/cli jinko auth login # → select "OAuth, sign in with browser" ``` The CLI displays a URL and code. Open it in any browser (works over SSH too), approve, and you're authenticated. Tokens are stored locally and refreshed automatically. CLI tokens cannot be reused as Bearer tokens on the MCP endpoint, they have different issuers. Use an API key (`jnk_*`) for programmatic MCP access. ## Connect via API Key For agents, scripts, CI/CD, or any environment without MCP OAuth support. Sign in at [the Jinko dashboard](https://gojinko.com/dashboard/keys), your key starts with `jnk_` and gives you 1,000 requests per month. ```bash theme={null} claude mcp add --transport http jinko https://mcp.builders.gojinko.com/mcp --header "Authorization: Bearer jnk_your_key" ``` ```json theme={null} { "jinko": { "transport": "streamable-http", "url": "https://mcp.builders.gojinko.com/mcp", "headers": { "Authorization": "Bearer jnk_your_key" } } } ``` ```toml theme={null} # ~/.codex/config.toml [mcp_servers.jinko] url = "https://mcp.builders.gojinko.com/mcp" bearer_token_env_var = "JINKO_API_KEY" ``` ```bash theme={null} export JINKO_API_KEY=jnk_your_key ``` ```json theme={null} // ~/.openclaw/openclaw.json { "mcpServers": { "jinko": { "type": "remote", "url": "https://mcp.builders.gojinko.com/mcp", "headers": { "Authorization": "Bearer jnk_your_key" } } } } ``` ```bash theme={null} jinko auth login --key jnk_your_key # Or via environment variable (no login needed) export JINKO_API_KEY=jnk_your_key ``` Connect to `https://mcp.builders.gojinko.com/mcp` with the `Authorization: Bearer jnk_your_key` header. ## Try it Ask your agent: > "Find me a flight from Paris to Barcelona next weekend" Or try these: * *"What are the cheapest destinations from London in June?"* * *"Search direct flights from JFK to LAX on May 15"* * *"Find roundtrip flights from CDG to NRT, 7 day trip in July"* * *"Find a 4-star hotel in Barcelona for July 15-18 for 2 adults"* * *"Build me a Paris weekend: flight from JFK and a hotel near the Louvre"* (multi-domain trip, one checkout) ## Build a booking flow For full step-by-step walkthroughs with side-by-side **MCP / SDK / CLI** variants, see the [Flight booking guide](/guides/flight-booking), the [Hotel booking guide](/guides/hotel-booking), or the combined [Flight + Hotel guide](/guides/flight-hotel-booking) for a single trip with two items. ## Tips for best results * **Use real traveler data**, never fabricate names, dates of birth, or passport details * **Airport codes first**, use IATA airport codes like `CDG`, `JFK`, or `NRT` * **Roundtrip searches** return both legs in a single offer, no need to search separately * **JSON format** gives your agent structured data, including the `trip_item_token` ## Need help? * [Dashboard](https://gojinko.com/dashboard), manage keys and check usage * [MCP tools reference](/tools/find-destination), all tools, parameters, and response formats * [CLI reference](/connect/cli), every command with usage and examples # Book Trip Source: https://docs.gojinko.com/tools/book Schedule checkout for a trip — returns a checkout URL the user opens to complete payment Turn a finalized trip into a checkout link the user can pay through. Use it once the trip is set and traveler details are filled in, for example after the user picks a Paris to Tokyo round trip and adds a hotel for the stay. The returned URL is what the user opens in a browser to complete payment. ```text theme={null} Schedule checkout for a trip — returns a Stripe checkout URL the user can open in a browser to complete payment. PREREQUISITES (call these first via the trip tool): trip(add_item) → add the chosen flight or hotel to the trip trip(upsert_travelers) → set traveler details + contact info trip(select_ancillaries) [optional] → add bags/seats/meals before quoting (flights only) USAGE: book({ trip_id }) The BFF schedules a quote, polls until it completes, schedules fulfillment, and returns a Stripe checkout URL — all in one synchronous call. Open the returned checkout_url in a browser to complete payment. Stripe webhooks finalize the booking after payment succeeds; no client-side confirm step is required. IMPORTANT: Never fabricate traveler data. Always make sure trip(add_item) and trip(upsert_travelers) have been called with real user-provided data first. ``` ## Parameters | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------- | | `trip_id` | `string` | Yes | Trip ID from the trip tool. The trip must have items (add\_item) and travelers (upsert\_travelers) set before booking. | ## Examples **Check out a ready trip:** ```json theme={null} { "name": "book", "arguments": { "trip_id": "42" } } ``` **Response:** ```json theme={null} { "status": "success", "trip_id": "42", "session_id": "123", "checkout_url": "https://app.gojinko.com/checkout?sid=123", "items": [ { "item_id": 7, "kind": "flight", "price": { "total": 842.30, "currency": "USD" }, "available_ancillaries": [ { "offer_id": "anc_bag_20kg", "type": "BAGGAGE", "price": 35.00, "name": "Extra 20kg bag" } ] } ] } ``` **What to do with the response:** 1. Open `checkout_url` in the user's browser (or your widget's `openLink`). 2. The user completes payment on Stripe. 3. Webhooks fulfill the booking, no client-side confirmation step needed. 4. Poll `get_trip` to watch `fulfillment.status` go `pending → fulfilling → completed`. `book` calls are idempotent per trip, calling it twice returns the same `session_id` and `checkout_url` until the session expires. # Find Dates Source: https://docs.gojinko.com/tools/find-dates Best date options for a route — up to ten cheapest itineraries, one per date-pair, spread across the month Answers "when should I fly?" for a known route. Takes the same inputs as Flight Calendar but returns up to ten cheapest itineraries — one per (departure, return) date-pair — spread across the requested departure window, so the user gets a diverse shortlist rather than ten near-adjacent cheapest days. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. ```text theme={null} Find the best date options for a known origin and destination using cached pricing. Takes the SAME inputs as flight_calendar, but returns up to ten cheapest itineraries — one per (departure, return) date-pair — spread across the requested departure window, so the user sees a diverse set of "when should I fly?" options rather than the full per-date list. WHEN TO USE THIS TOOL: - The user knows the route (origin AND destination) and is flexible on WHEN, and wants a short, spread-out shortlist of the best date options. - Examples: "When is the cheapest time to fly Paris → New York in June?", "Best weekends to go from London to Lisbon next month", "Give me a few good date options for a week in Tokyo". WHEN TO USE flight_calendar INSTEAD: - The user wants the full price-per-date list / calendar grid for a route, not a curated shortlist. WHEN TO USE flight_search INSTEAD: - The user has committed to EXACT dates (single departure AND single return). flight_search hits live pricing and is the step before booking. IMPORTANT: All dates MUST be in the future. Never use past dates. Origin and destination must be IATA city codes by default, or IATA airport codes if the user specifies them. By default search roundtrip unless the user explicitly asks for one-way (trip_type="oneway"). Flow: find_dates → flight_search (price-check the chosen dates) → trip → book ``` ## Parameters | Name | Type | Required | Description | | ----------------------- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | | `origin` | `string` | Yes | Origin airport IATA code or city code (3 letters). Examples: "JFK", "PAR". | | `destination` | `string` | Yes | Destination airport IATA code or city code (3 letters). Examples: "CDG", "NRT". | | `trip_type` | `enum ("oneway" \| "roundtrip")` | Yes | Trip type: "oneway" or "roundtrip". | | `departure_dates` | `array` | No | Specific departure dates (YYYY-MM-DD). Multiple dates searched with OR logic. | | `departure_date_ranges` | `array` | No | Departure date ranges for flexible search. | | `return_dates` | `array` | No | Specific return dates (YYYY-MM-DD) for round-trip flights. | | `return_date_ranges` | `array` | No | Return date ranges for flexible round-trip search. | | `stay_days` | `integer` | No | Exact stay duration in days. Auto-calculates return date. | | `stay_days_range` | `object` | No | Flexible stay duration range. Example: \{min: 5, max: 10} | | `stay_days_range.min` | `integer` | Yes | Minimum stay duration in days | | `stay_days_range.max` | `integer` | Yes | Maximum stay duration in days | | `direct_only` | `boolean` | No | Only return nonstop flights. | | `cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. | | `max_total` | `number` | No | Maximum total price for the trip (canonical name). Preferred over max\_price. | | `max_price` | `number` | No | Deprecated alias for max\_total. Use max\_total instead. | | `sort_by` | `enum ("lowest" \| "recommendation")` | No | Sort order. Default: "lowest" (cheapest first). | | `currency` | `string` | No | ISO 4217 currency code. Defaults to "USD". | | `locale` | `string` | No | BCP 47 locale. Defaults to "en-US". | | `format` | `enum ("text" \| "json")` | No | Response format. "text" returns plain text for LLMs. "json" returns structured JSON. | | `limit` | `integer` | No | Max date-pairs to return (1-100). Default 20. | # Find Destination Source: https://docs.gojinko.com/tools/find-destination Discover travel destinations accessible from your departure airports Surface inspiration when a user knows where they want to leave from but not where they want to go. Typical prompts include "cheap beach getaways from New York" or "weekend trips out of London under €200". Results come back ranked by lowest available fare so the user can compare options before committing to a route. ```text theme={null} Discover travel destinations accessible from your departure airports. Search globally or filter to specific regions. Returns destinations sorted by cheapest available flight. IMPORTANT: Use airport codes (CDG, ORY, JFK), NOT city codes (PAR, NYC). Include all nearby airports for best results (e.g., CDG + ORY for Paris). Next step: Use flight_calendar with the destination to get specific flights with offer_tokens for pricing. ``` ## Parameters | Name | Type | Required | Description | | ----------------------- | ---------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `origins` | `array` | Yes | Origin airport IATA codes or city codes (3 letters). Include all nearby airports. Examples: \["JFK", "LGA", "EWR"] for NYC. | | `destinations` | `array` | No | Filter to specific destination IATA codes. Omit for global discovery mode. | | `trip_type` | `enum ("oneway" \| "roundtrip")` | Yes | Trip type: "oneway" or "roundtrip". | | `departure_dates` | `array` | No | Specific departure dates (YYYY-MM-DD). Multiple dates searched with OR logic. | | `departure_date_ranges` | `array` | No | Departure date ranges for flexible search. | | `return_dates` | `array` | No | Specific return dates (YYYY-MM-DD) for round-trip flights. | | `return_date_ranges` | `array` | No | Return date ranges for flexible round-trip search. | | `stay_days` | `integer` | No | Exact stay duration in days. | | `stay_days_range` | `object` | No | Flexible stay duration range. Example: \{min: 5, max: 10} | | `stay_days_range.min` | `integer` | Yes | Minimum stay duration in days | | `stay_days_range.max` | `integer` | Yes | Maximum stay duration in days | | `direct_only` | `boolean` | No | Only return nonstop flights. | | `cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. | | `max_total` | `number` | No | Maximum total price for the trip (canonical name). Preferred over max\_price. | | `max_price` | `number` | No | Deprecated alias for max\_total. Use max\_total instead. | | `sort_by` | `enum ("lowest" \| "recommendation")` | No | Sort order. Default: "lowest" (cheapest first). | | `limit` | `integer` | No | Max destinations to return per page (1-100). Default 20. | | `offset` | `integer` | No | Number of destinations to skip, for pagination. Default 0. | | `currency` | `string` | No | ISO 4217 currency code. Defaults to "USD". | | `locale` | `string` | No | BCP 47 locale. Defaults to "en-US". | | `format` | `enum ("text" \| "json")` | No | Response format. "text" returns plain text for LLMs. "json" returns structured JSON. | ## Examples **Explore destinations under \$500 from New York in June:** ```json theme={null} { "name": "find_destination", "arguments": { "origins": ["JFK", "LGA", "EWR"], "trip_type": "roundtrip", "departure_date_ranges": [{ "start": "2026-06-01", "end": "2026-06-30" }], "stay_days_range": { "min": 5, "max": 10 }, "max_price": 500, "currency": "USD" } } ``` **Europe from Paris in spring, direct only:** ```json theme={null} { "name": "find_destination", "arguments": { "origins": ["CDG", "ORY"], "destinations": ["LHR", "AMS", "FRA", "MAD", "BCN", "ROM"], "trip_type": "roundtrip", "departure_date_ranges": [{ "start": "2026-04-01", "end": "2026-05-31" }], "stay_days": 3, "direct_only": true, "currency": "EUR" } } ``` The response is a list of destinations sorted by cheapest found price, each with an `offer_token` you can pass into `flight_search` for live pricing. # Flight Calendar Source: https://docs.gojinko.com/tools/flight-calendar Search flights between a known origin and destination for flexible dates Find priced itineraries between a known origin and destination using cached results, ideal when the user is flexible on dates. It answers questions like "cheapest week to fly Paris to Barcelona in June" or "best Friday to Sunday options from JFK to LAX next month". Each result includes an offer token you can pass into a live price check or directly into a trip. ```text theme={null} Search flights between a known origin and destination using cached pricing. Use this tool whenever the user specifies BOTH where they are flying FROM and where they are flying TO. WHEN TO USE THIS TOOL (CRITICAL): - The user provides both an origin AND a destination (city or airport) - Examples: "Paris to Barcelona", "JFK to CDG", "London to NYC for a weekend" - Supports loose / flexible dates: single dates, date arrays, date ranges, stay_days - ALSO the right tool for "cheapest flight", "best flight", "find me a flight", "cheapest date" phrasings — returns the cheapest cached itineraries. WHEN TO USE find_destination INSTEAD: - The user does NOT specify a destination: "Where should I go from Paris?", "Best deals from NYC" - The user wants inspiration: "Beach destinations from London", "Cheap flights from SF" WHEN TO USE flight_search INSTEAD: - The user has committed to EXACT dates — single departure date AND single return date on one specific route. - Example: "Paris → NYC, June 17 → June 26" - flight_search hits live pricing (each call has a cost) and is the step immediately before booking. Use only once route + both dates are locked. IMPORTANT: All dates in query parameters (departure_dates, departure_date_ranges, return_dates, return_date_ranges) MUST be in the future. Never use past dates. Please fill as much as possible search parameters based on user intent to get best results. Origin and destination must be IATA city code by default except if the user specifies IATA Airport code in the search. ROUTE SEARCH: - Use exact 3-letter IATA airport codes or IATA city code for both origin and destination - Date ranges OR stay duration for flexible trip planning - Natural trip duration (stay_days) instead of exact return dates - By default, please search roundtrip flights unless user specifies one-way. Use trip_type="oneway" ONLY when the user explicitly asks for a one-way trip USE CASES: ✓ "Find flights from JFK to CDG next month" - Specific route with date range ✓ "Fly from Los Angeles to Tokyo for a week in December" - Uses departure_date + stay_days ✓ "Paris to Barcelona for a weekend in April" - Specific route ✓ "Cheapest flight from ORD to LHR under $600" - Specific route with budget ✓ "Direct flight in business class from New York to London" - Specific route with preferences Flow: flight_calendar → flight_search (price-check) → trip → book ``` ## Parameters | Name | Type | Required | Description | | ----------------------- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | | `origin` | `string` | Yes | Origin airport IATA code or city code (3 letters). Examples: "JFK", "PAR". | | `destination` | `string` | Yes | Destination airport IATA code or city code (3 letters). Examples: "CDG", "NRT". | | `trip_type` | `enum ("oneway" \| "roundtrip")` | Yes | Trip type: "oneway" or "roundtrip". | | `departure_dates` | `array` | No | Specific departure dates (YYYY-MM-DD). Multiple dates searched with OR logic. | | `departure_date_ranges` | `array` | No | Departure date ranges for flexible search. | | `return_dates` | `array` | No | Specific return dates (YYYY-MM-DD) for round-trip flights. | | `return_date_ranges` | `array` | No | Return date ranges for flexible round-trip search. | | `stay_days` | `integer` | No | Exact stay duration in days. Auto-calculates return date. | | `stay_days_range` | `object` | No | Flexible stay duration range. Example: \{min: 5, max: 10} | | `stay_days_range.min` | `integer` | Yes | Minimum stay duration in days | | `stay_days_range.max` | `integer` | Yes | Maximum stay duration in days | | `direct_only` | `boolean` | No | Only return nonstop flights. | | `cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. | | `max_total` | `number` | No | Maximum total price for the trip (canonical name). Preferred over max\_price. | | `max_price` | `number` | No | Deprecated alias for max\_total. Use max\_total instead. | | `sort_by` | `enum ("lowest" \| "recommendation")` | No | Sort order. Default: "lowest" (cheapest first). | | `currency` | `string` | No | ISO 4217 currency code. Defaults to "USD". | | `locale` | `string` | No | BCP 47 locale. Defaults to "en-US". | | `format` | `enum ("text" \| "json")` | No | Response format. "text" returns plain text for LLMs. "json" returns structured JSON. | | `limit` | `integer` | No | Max results to return per page (1-100). Default 20. | | `offset` | `integer` | No | Number of results to skip, for pagination. Default 0. | ## Examples **Cheapest days to fly JFK→CDG in June:** ```json theme={null} { "name": "flight_calendar", "arguments": { "origin": "JFK", "destination": "CDG", "trip_type": "roundtrip", "departure_date_start": "2026-06-01", "departure_date_end": "2026-06-30", "stay_days": 7, "currency": "USD" } } ``` **One-way, direct-only, business class:** ```json theme={null} { "name": "flight_calendar", "arguments": { "origin": "CDG", "destination": "NRT", "trip_type": "oneway", "departure_date_start": "2026-09-01", "departure_date_end": "2026-09-30", "cabin_class": "business", "direct_only": true, "currency": "EUR" } } ``` The response is a list of the cheapest flights found across the date range — not one entry per day. Each entry includes an `offer_token`; feed it to `flight_search` for live pricing before booking. # Flight Exchange Source: https://docs.gojinko.com/tools/flight-exchange Exchange a booked flight for a different itinerary ```text theme={null} Exchange a booked flight for a different itinerary. No login required — authenticate with the Jinko booking reference and traveler last name. WORKFLOW: 1. action="shop" with booking_ref + last_name + optional preferred_departure_date → browse exchange options 2. action="price" with booking_ref + last_name + offer_id → get exact pricing (fare difference, penalties) 3. If user confirms, action="commit" with booking_ref + last_name + offer_id + session_reference → execute the exchange 4. action="status" with booking_ref + last_name → poll exchange progress IMPORTANT: - Always shop before pricing, price before committing. - Get explicit user confirmation before committing — exchanges may involve fare differences (additional payment or refund). - The session_reference from pricing must be passed to commit. ``` ## Parameters | Name | Type | Required | Description | | -------------------------- | -------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `action` | `enum ("shop" \| "price" \| "commit" \| "status")` | Yes | Action to perform: "shop" to browse exchange alternatives, "price" to get exact pricing for an offer, "commit" to execute the exchange, "status" to poll exchange progress | | `booking_ref` | `string` | Yes | Jinko booking reference (e.g. JNK-A7B3X9). Found in the booking confirmation email. | | `last_name` | `string` | Yes | Last name of the primary traveler on the booking. | | `order_id` | `string` | No | Provider order ID. Optional — provided only by authenticated DevPlatform callers who already resolved it. | | `provider` | `string` | No | Provider code (e.g., "travelfusion", "sabre"). Usually auto-detected from the booking. | | `ticket_numbers` | `array` | No | Specific ticket numbers to exchange (for partial exchanges). Omit for full booking. | | `offer_id` | `string` | No | Exchange offer ID returned from a previous shop action (canonical name). Required for price and commit actions. Preferred over exchange\_offer\_id. | | `exchange_offer_id` | `string` | No | Deprecated alias for offer\_id. Use offer\_id instead. | | `session_reference` | `string` | No | Session reference returned from a previous price action. Required for commit action. | | `preferred_departure_date` | `string` | No | Preferred departure date for the new flight (YYYY-MM-DD format). Used with shop action. | ## Examples **Shop for exchange options (guest path):** ```json theme={null} { "name": "flight_exchange", "arguments": { "action": "shop", "booking_ref": "JNK-ABC123", "last_name": "Doe", "preferred_departure_date": "2026-07-15" } } ``` Response lists alternative itineraries with `offer_id` per option. **Price a specific offer:** ```json theme={null} { "name": "flight_exchange", "arguments": { "action": "price", "booking_ref": "JNK-ABC123", "last_name": "Doe", "offer_id": "exch_offer_abc" } } ``` Returns `price_delta` (can be positive or negative), `airline_penalty`, `service_fee`, and a `session_reference` to commit against. **Commit the exchange:** ```json theme={null} { "name": "flight_exchange", "arguments": { "action": "commit", "booking_ref": "JNK-ABC123", "last_name": "Doe", "offer_id": "exch_offer_abc", "session_reference": "sess_xyz789" } } ``` **Poll status:** ```json theme={null} { "name": "flight_exchange", "arguments": { "action": "status", "booking_ref": "JNK-ABC123", "last_name": "Doe", "exchange_reference": "EXC-abc123" } } ``` The 4-step flow is serial, each step produces the token/reference the next needs. Always surface the priced delta (step 2) to the user for confirmation before calling `commit` (step 3). # Flight Refund Source: https://docs.gojinko.com/tools/flight-refund Check refund eligibility, commit a refund, or check refund status for a booked flight ```text theme={null} Check refund eligibility, commit a refund, or check refund status for a booked flight. No login required — authenticate with the Jinko booking reference and traveler last name. PREREQUISITES: - booking_ref (JNK-XXXXXX format) and last_name of the primary traveler from the booking confirmation email. WORKFLOW: 1. action="check" with booking_ref + last_name → review eligibility, amounts, penalties 2. If refundable and user confirms, action="commit" with booking_ref + last_name → capture refund_reference 3. action="status" with booking_ref + last_name (+ optional refund_reference) → poll progress IMPORTANT: - Always check eligibility before committing. - Always get explicit user confirmation before committing a refund. - Some refunds require manual processing — the response flags support_level and is_automatable. - Refund amounts may include penalties. ``` ## Parameters | Name | Type | Required | Description | | ------------------ | ---------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ | | `action` | `enum ("check" \| "commit" \| "status")` | Yes | Action to perform: "check" to check refund eligibility, "commit" to confirm the refund, "status" to poll refund progress | | `booking_ref` | `string` | Yes | Jinko booking reference (e.g. JNK-A7B3X9). Found in the booking confirmation email. | | `last_name` | `string` | Yes | Last name of the primary traveler on the booking. | | `order_id` | `string` | No | Provider order ID. Optional — provided only by authenticated DevPlatform callers who already resolved it. | | `provider` | `string` | No | Provider code (e.g., "travelfusion", "sabre"). Usually auto-detected from the booking. | | `ticket_numbers` | `array` | No | Specific ticket numbers to refund (for partial refunds). Omit for full booking refund. | | `refund_reference` | `string` | No | Refund reference ID returned from a previous commit action. Required for status checks. | ## Examples **Check refund eligibility (authenticated path):** ```json theme={null} { "name": "flight_refund", "arguments": { "action": "check", "order_id": "TF-ORDER-123" } } ``` **Check refund eligibility (guest path):** ```json theme={null} { "name": "flight_refund", "arguments": { "action": "check", "booking_ref": "JNK-ABC123", "last_name": "Doe" } } ``` **Commit a refund after checking eligibility:** ```json theme={null} { "name": "flight_refund", "arguments": { "action": "commit", "booking_ref": "JNK-ABC123", "last_name": "Doe" } } ``` Response includes a `refund_reference`. Poll `refund_status` until terminal: ```json theme={null} { "name": "flight_refund", "arguments": { "action": "status", "booking_ref": "JNK-ABC123", "last_name": "Doe", "refund_reference": "REF-xyz789" } } ``` Terminal states: `succeeded`, `failed`, `cancelled`. Poll every \~15-30 seconds. `check` is read-only and never triggers a refund. Always show eligibility + `refundable_amount` to the user and get explicit confirmation before calling `commit`. # Flight Search Source: https://docs.gojinko.com/tools/flight-search Get live flight pricing — search by route, or re-price a known offer Fetch live, bookable pricing for a specific route and date pair. Use it once the user has settled on exact travel dates, for example "Paris to New York departing June 1 returning June 8 in economy". It also reprices an offer surfaced earlier by the calendar or destination tools so you can confirm availability before adding it to a trip. ```text theme={null} Get live flight pricing and fare options. Provide exactly one of the "search" or "price_check" nested objects: 1. search: Live flight search by route and dates. Example: { "search": { "origin": "PAR", "destination": "NYC", "departure_date": "2025-06-01" } } Required fields: origin, destination, departure_date. Optional: return_date, cabin_class, direct_only, origin_type, destination_type. 2. price_check: Get live pricing for a specific flight deal from discovery tools (flight_calendar, find_destination, flight_calendar). Example: { "price_check": { "offer_token": "token_from_discovery" } } IMPORTANT: "search" and "price_check" are nested objects, not string values. Do NOT pass them as strings. RESPONSE: - Each flight includes detailed segments, fare options with baggage/refund/change rules, and a trip_item_token per fare. - price_check may return status "flight_unavailable" with alternatives if the flight is no longer available — ask the user to choose. NEXT STEP: Use the trip tool with add_item and the trip_item_token from the fare the user selects. Flow: discovery (flight_calendar / find_destination / flight_calendar) or direct search → flight_search → trip → book ``` ## Parameters | Name | Type | Required | Description | | ------------------------- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `search` | `object` | No | Live flight search by route and dates. Use city codes by default (PAR, NYC); use airport codes (CDG, JFK) only when the user specifies a particular airport. | | `search.origin` | `string` | Yes | Origin IATA city code (e.g. PAR, NYC, LON) or airport code (e.g. CDG, JFK, LHR). City codes preferred — they search all airports in the city. | | `search.origin_type` | `enum ("city" \| "airport")` | No | Whether origin is a city code or airport code. Defaults to "city". | | `search.destination` | `unknown` | Yes | Destination IATA city code (e.g. MIL, BCN, TYO) or airport code (e.g. MXP, BCN, NRT). City codes preferred. | | `search.destination_type` | `enum ("city" \| "airport")` | No | Whether destination is a city code or airport code. Defaults to "city". | | `search.departure_date` | `string` | Yes | Departure date (YYYY-MM-DD) | | `search.return_date` | `string` | No | Return date (YYYY-MM-DD) for round-trip. | | `search.cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. | | `search.direct_only` | `boolean` | No | Only return nonstop flights. | | `search.limit` | `integer` | No | Max results to return (1-100). Default 20. Caps how many flights come back; only trims the set, since providers bound the real count. | | `price_check` | `object` | No | Get live pricing for a specific flight deal. Returns confirmed fares with trip\_item\_token for booking. | | `price_check.offer_token` | `string` | Yes | offer\_token from flight\_calendar, find\_destination, or flight\_calendar results. | | `passengers` | `object` | No | Passenger counts. Defaults to 1 adult. | | `passengers.adults` | `integer` | No | Adult travelers (12+) | | `passengers.children` | `integer` | No | Child travelers (2-11) | | `passengers.infants` | `integer` | No | Infant travelers (under 2) | | `currency` | `string` | No | ISO 4217 currency code. Defaults to "USD". | | `locale` | `string` | No | BCP 47 locale. Defaults to "en-US". | ## Examples **Price-check a specific offer from discovery:** ```json theme={null} { "name": "flight_search", "arguments": { "price_check": { "offer_token": "offer_ABc123xYz..." } } } ``` **Live search by route (no prior discovery):** ```json theme={null} { "name": "flight_search", "arguments": { "search": { "origin": "PAR", "destination": "NYC", "departure_date": "2026-06-15", "return_date": "2026-06-22", "direct_only": false, "cabin_class": "economy" } } } ``` **Live search with passenger mix + max price filter:** ```json theme={null} { "name": "flight_search", "arguments": { "search": { "origin": "CDG", "destination": "JFK", "departure_date": "2026-07-01", "passengers": { "adults": 2, "children": 1 }, "max_price": 1200, "direct_only": true } } } ``` The response has detailed segment info per itinerary and multiple fare options per itinerary (economy / premium / business), each with a `trip_item_token` you pass to `trip(add_item)`. If `price_check` returns `status: "flight_unavailable"`, the offer sold out, use the `alternatives[]` in the response or loop back to discovery. # Get Booking Source: https://docs.gojinko.com/tools/get-booking Retrieve a booking using the Jinko booking reference and the traveler's last name Anonymous retrieval for a booking the user already made. Use it when the traveler has their Jinko booking reference and last name, for example to look up the itinerary days later without signing in. Returns the full booking envelope: status, travelers, and itinerary items with confirmation numbers (PNR for flights, confirmation number for hotels). ```text theme={null} Retrieve a booking using the Jinko booking reference and the traveler's last name. No login required. USAGE: get_booking({ booking_ref: "JNK-A7B3X9", last_name: "Doe" }) Returns booking details: status, travelers, itinerary items with confirmation numbers (PNR for flights, confirmation number for hotels). The booking reference is found in the confirmation email sent after booking. Format: JNK-XXXXXX (6 uppercase alphanumeric characters). ``` ## Parameters | Name | Type | Required | Description | | ------------- | -------- | -------- | ----------------------------------------------------------------------------------- | | `booking_ref` | `string` | Yes | Jinko booking reference (e.g. JNK-A7B3X9). Found in the booking confirmation email. | | `last_name` | `string` | Yes | Last name of the primary traveler on the booking. | ## Examples **Guest lookup by Jinko reference + last name:** ```json theme={null} { "name": "get_booking", "arguments": { "booking_ref": "JNK-ABC123", "last_name": "Doe" } } ``` Returns the booking envelope (itineraries, travelers, status). No auth required, this endpoint is guest-accessible so end users can check their own reservations without signing into a Jinko account. **Error handling:** The endpoint deliberately returns the same generic 404 for both "booking does not exist" and "last\_name doesn't match this booking\_ref", existence non-leak is intentional. If you get a 404, don't retry with variations; either the user typoed the ref or the booking was never made under this last\_name. # Get Trip Source: https://docs.gojinko.com/tools/get-trip Fetch the full lifecycle state of a trip — items, travelers, quote, fulfillment, and any booking references Inspect the current state of a trip without modifying it. Reach for it when you need to confirm what items are on the trip, verify the travelers attached to a booking, or check whether a checkout has finalized after the user paid. The response covers items, traveler details, quote status, and any booking references that have been issued. ```text theme={null} Fetch the full lifecycle state of a trip — cart contents, travelers, quote status, fulfillment status, and any booking references already produced. USAGE: get_trip({ trip_id }) This is a read-only call. Use it to inspect a trip after trip(add_item), trip(upsert_travelers), or book — for example to confirm what items / travelers are currently on the cart, or to check whether a booking has been finalized post-checkout. ``` ## Parameters | Name | Type | Required | Description | | --------- | -------- | -------- | -------------------------------------------------------------- | | `trip_id` | `string` | Yes | Trip ID returned from a previous trip(add\_item) or book call. | ## Examples **Inspect a trip's lifecycle state:** ```json theme={null} { "name": "get_trip", "arguments": { "trip_id": "42" } } ``` **Abbreviated response:** ```json theme={null} { "trip_id": "42", "status": "fulfilling", "items": [ { "item_id": 7, "kind": "flight", "trip_item_token": "...", "price": { "total": 842.30 } } ], "travelers": [{ "first_name": "Jane", "last_name": "Doe", "passenger_type": "ADULT" }], "quote": { "status": "succeeded", "totals": { "subtotal": 842.30, "fees": 0, "total": 842.30, "currency": "USD" } }, "fulfillment": { "status": "fulfilling", "scheduled_at": "2026-04-21T15:00:00Z" }, "bookings": [] } ``` Once `fulfillment.status` is `completed`, `bookings[]` populates with `booking_ref` (Jinko reference) and `pnr` (airline reference). These are what you surface in confirmation emails or share with the customer. # Cancel Hotel Booking Source: https://docs.gojinko.com/tools/hotel-cancel Cancel a hotel booking and get a refund when eligible Cancel a hotel booking when the traveler can no longer make the stay or wants to drop a hotel from a multi-item trip. The call is idempotent: retrying the same cancellation re-serves the stored result rather than charging or refunding twice. Works with guest auth (booking ref + last name) or the authenticated shortcut (provider booking ID). ```text theme={null} Cancel a hotel booking. USAGE (guest — no login required): hotel_cancel({ booking_ref: "JNK-A7B3X9", last_name: "Doe" }) USAGE (authenticated shortcut, when caller already has the provider's booking ID): hotel_cancel({ provider_booking_id: "", provider: "nuitee" }) The two auth modes are MUTUALLY EXCLUSIVE — pass either the guest pair or the provider_booking_id, never both. Returns: cancellation status, refund amount (if any), penalty amount (if any), and the provider reference. IDEMPOTENT — calling this on an already-cancelled booking returns the same result that was recorded the first time, with `idempotent: true` in the structured response. Safe to retry. Before cancelling, you can call `get_booking` first to inspect the booking details and confirm what you are about to cancel. ``` ## Parameters | Name | Type | Required | Description | | --------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `booking_ref` | `string` | No | Jinko booking reference (e.g. JNK-A7B3X9). Found in the booking confirmation email. Guest path — must be paired with last\_name. | | `last_name` | `string` | No | Last name of the lead guest on the hotel booking. Guest path — must be paired with booking\_ref. | | `provider_booking_id` | `string` | No | Provider booking ID (e.g. the Nuitée booking ID). Optional — provided only by authenticated DevPlatform callers who already resolved it. Mutually exclusive with booking\_ref + last\_name. | | `provider` | `string` | No | Provider code (e.g. "nuitee"). Usually auto-detected from the booking. Only meaningful alongside provider\_booking\_id. | # Hotel Details Source: https://docs.gojinko.com/tools/hotel-details Fetch rich metadata (gallery, facilities, policies, per-room details) for a single hotel Pull the full marketing and operational profile of a single property after a search result catches the user's attention. Useful for questions like "what amenities does this hotel have", "is there a pool on site", or "what is the cancellation policy on the deluxe room". Returns the gallery, facilities, room metadata, and policies in one payload. ```text theme={null} Fetch rich metadata (gallery, facilities, policies, per-room metadata) for a single hotel. Use this AFTER hotel_search returns a list of hotels and the user wants a closer look at one. Pass the hotel_id from a hotel_search result. REQUIRED: - hotel_id: string (from a hotel_search offer) OPTIONAL: - checkin, checkout (YYYY-MM-DD): accepted for cache-key alignment; currently ignored by the BFF. RESPONSE: - hotel: { id, name, star_rating, address, images[], facilities[], policies[] } - rooms[]: per-room metadata, each with name + description (when available) Notes: - Read-only. Does not affect the cart or quote. - Independent of pricing — call hotel_search first to get live rates with offer tokens. ``` ## Parameters | Name | Type | Required | Description | | ---------- | -------- | -------- | -------------------------------------------------------------------------------------------------- | | `hotel_id` | `string` | Yes | Hotel ID (from a prior hotel\_search offer). | | `checkin` | `string` | No | Check-in date (YYYY-MM-DD). Accepted for future cache-key alignment; currently unused by the BFF. | | `checkout` | `string` | No | Check-out date (YYYY-MM-DD). Accepted for future cache-key alignment; currently unused by the BFF. | ## Examples **Fetch full details for a single hotel returned by `hotel_search`:** ```json theme={null} { "name": "hotel_details", "arguments": { "hotel_id": "lpe2264" } } ``` **With dates passed for cache alignment:** ```json theme={null} { "name": "hotel_details", "arguments": { "hotel_id": "lpe2264", "checkin": "2026-07-15", "checkout": "2026-07-18" } } ``` The response carries hotel-level metadata (images, facilities, policies) plus per-room details (room name + description). Read-only — doesn't affect a trip or quote. # Hotel Search Source: https://docs.gojinko.com/tools/hotel-search Search live hotel inventory and rates Search live hotel inventory and nightly rates for a destination and stay window. It handles requests like "three nights in Lisbon next weekend for two adults" or "family room in Rome with one child in August". Each result includes an `htl_*` offer token you can hand to the trip tool to start a booking. ```text theme={null} Search live hotel inventory and rates. REQUIRED: - destination: object — two distinct modes. Mode A (rate lookup): { hotel_name (+ optional country_code, city_name) } or { hotel_ids }. Mode B (hotel search): { query }, { city_name + country_code }, { latitude + longitude (+ radius_km) }, or { place_id }. - checkin, checkout: YYYY-MM-DD - occupancy: either { occupancies: [{ adults, children_ages? }, ...] } (one entry per room) OR shorthand { adults, children?, rooms? } TWO MODES — pick deliberately: MODE A (rate lookup — the user named a specific hotel): - { hotel_name }: free-text hotel name ("Hotel Calimala", "The St. Regis Rome", "Hôtel Costes"). Server fuzzy-matches against a 1.74M-hotel catalog. ALWAYS pair with country_code AND city_name when known — lookup precision drops sharply on common names without scope. Returns 422 HOTEL_NAME_LOW_CONFIDENCE if no candidate scores ≥ 0.7; see "ERROR HANDLING" below. - { hotel_ids }: re-shop a known set (from a prior search result). In Mode A: filters are ignored (user named the property), and the response includes nearby_alternatives — up to 5 hotels within ~2km of the matched property, in the same response shape so the user can compare. MODE B (hotel search — the user is exploring a destination): - { query }: unambiguous cities or well-known POIs only ("Paris", "Times Square"). Provider AI search returns 0 for islands ("Menorca", "Santorini", "Mykonos"), regions ("Tuscany", "Provence", "Bavaria"), countries, archipelagos. Do NOT use { query } for those. - { city_name + country_code }: when the user named a city, even if ambiguous. Best when the destination has a primary city ("Mahón, ES" for Menorca; "Florence, IT" for Tuscany). - { latitude + longitude + radius_km }: when the destination is an area, island, or region with no obvious primary city. radius_km up to 50. - { place_id }: when you already have an upstream Place ID. If the user names something non-city (an island, region, archipelago, neighborhood), DO NOT pass it as { query } — pick { city_name+country_code } or { latitude+longitude+radius_km }. ERROR HANDLING — 422 HOTEL_NAME_LOW_CONFIDENCE (Mode A only): When { hotel_name } fuzzy lookup finds no candidate ≥ 0.7, the response body is: { "error": { "code": "HOTEL_NAME_LOW_CONFIDENCE", "message": "...", "top_candidates": [{hotel_id, name, city, score}], "suggested_retry": { "destination": {...} } } } This is ACTIONABLE, not fatal. Pick one: 1. Top candidate matches what the user meant (typo/spelling) → confirm with the user, then retry with { hotel_ids: [""] }. 2. None of the candidates fit → ask the user "I couldn't pin down 'X' — want me to search all hotels in instead?" then retry with suggested_retry.destination. 3. User likely meant a different city → ask to clarify, then retry hotel_name with corrected country_code/city_name. Don't silently auto-pick a low-confidence candidate — booking the wrong hotel is worse than asking one clarifying question. OPTIONAL: - currency (ISO 4217), guest_nationality (ISO 3166-1 alpha-2) - filters: { min_rating, min_star_rating, max_star_rating, min_reviews, hotel_type_ids, chain_ids, facility_ids, max_results } EXAMPLES: 1. Free-text city search: { "destination": { "query": "Paris" }, "checkin": "2026-07-15", "checkout": "2026-07-18", "adults": 2 } 2. Two-room family with kids: { "destination": { "city_name": "Barcelona", "country_code": "es" }, "checkin": "2026-08-01", "checkout": "2026-08-05", "occupancies": [{ "adults": 2 }, { "adults": 1, "children_ages": [5, 7] }] } 3. Island/region (use lat-lng + radius, NOT query): { "destination": { "latitude": 39.9496, "longitude": 4.1102, "radius_km": 30 }, "checkin": "2026-08-31", "checkout": "2026-09-09", "adults": 1 } 4. Geo-radius search around a POI: { "destination": { "latitude": 41.4036, "longitude": 2.1744, "radius_km": 3 }, "checkin": "2026-09-10", "checkout": "2026-09-12", "adults": 2 } 5. Mode A — user named a specific hotel: { "destination": { "hotel_name": "Hotel Calimala", "country_code": "it", "city_name": "Florence" }, "checkin": "2026-07-15", "checkout": "2026-07-18", "adults": 2, "currency": "EUR" } RESPONSE: - Each hotel includes basic metadata (name, address, star_rating, rating, main_photo) and a rooms[] list. - Each room has a rates[] list. Each rate has an offer_id (the htl_* token), board type, refund policy, and total_amount + currency. NEXT STEP: Use the trip tool with add_item and the offer_id of the rate the user picks. Hotel items work alongside flight items in the same cart. Flow: hotel_search → trip(add_item) → trip(upsert_travelers) → book ``` ## Parameters | Name | Type | Required | Description | | -------------------------- | ---------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `destination` | `object` | Yes | Destination — provide exactly one shape. Two distinct modes: MODE A (rate lookup — you know which hotel): • \{ hotel\_ids } to re-shop a known set. • \{ hotel\_name, country\_code?, city\_name? } when the user named a specific property. Server resolves via fuzzy lookup; returns 422 HOTEL\_NAME\_LOW\_CONFIDENCE if no candidate scores ≥ 0.7. MODE B (hotel search — you're exploring): • \{ query } for unambiguous cities/POIs only ("Paris", "Times Square"). Provider AI search returns 0 for islands/regions/countries/archipelagos. • \{ city\_name + country\_code } for ambiguous city names or when the user named a primary city ("Mahón, ES" for Menorca). • \{ latitude + longitude + radius\_km } for islands, regions, neighborhoods — anywhere \{ query } returns 0. • \{ place\_id } when you already have an upstream Place ID. In Mode A, filters (min\_rating / star / facility / chain / hotel\_type / max\_results) are ignored — the user already named the property. Best practice: don't combine filters with hotel\_ids or hotel\_name. | | `destination.query` | `string` | No | Free-text destination — use ONLY for unambiguous cities or well-known POIs (e.g. "Paris", "Times Square"). Provider-side AI search reliably returns 0 results for islands ("Menorca", "Santorini"), regions ("Tuscany", "Provence"), countries, archipelagos, and other non-city geographies. For those: prefer \{ city\_name + country\_code } when a primary city is implied (e.g. "Mahón, ES" for Menorca), or \{ latitude + longitude + radius\_km } to cover an area. Max 200 chars. | | `destination.city_name` | `string` | No | City name (e.g. "Paris"). In Mode B: pair with country\_code as the destination. In Mode A (with hotel\_name): pair with hotel\_name to narrow the fuzzy-lookup scope. | | `destination.country_code` | `string` | No | ISO 3166-1 alpha-2 country code (lowercase preferred, e.g. "fr"). Must be paired with city\_name OR hotel\_name. In Mode B it disambiguates the city; in Mode A it narrows the fuzzy lookup. | | `destination.latitude` | `number` | No | Latitude for geo-radius search. Pair with longitude. | | `destination.longitude` | `number` | No | Longitude for geo-radius search. Pair with latitude. | | `destination.radius_km` | `number` | No | Geo-radius in km (default 5, max 50). Requires latitude+longitude — ignored with other destination shapes. | | `destination.place_id` | `string` | No | Google Places ID or upstream place identifier. | | `destination.hotel_ids` | `array` | No | Mode A — re-shop a known set of hotel IDs (skips destination resolution). | | `destination.hotel_name` | `string` | No | Mode A — free-text hotel name when the user named a specific property they want to book (e.g. "Hotel Calimala", "The St. Regis Rome", "Hôtel Costes"). Server runs a fuzzy trigram match over the 1.74M-hotel catalog; uses the top hit when its confidence is ≥ 0.7 (auto-pick safe). If no candidate clears that threshold, returns HTTP 422 with error.code = HOTEL\_NAME\_LOW\_CONFIDENCE + top\_candidates + suggested\_retry — the agent should confirm a candidate with the user or fall back to the suggested city destination. ALWAYS pair with country\_code and city\_name when known; lookup precision drops sharply on common names without scope. | | `checkin` | `string` | Yes | Check-in date (YYYY-MM-DD). | | `checkout` | `string` | Yes | Check-out date (YYYY-MM-DD). | | `occupancies` | `array` | No | One entry per room (structured). PREFERRED whenever the party is larger than 2 adults or has children — it removes ambiguity about how guests are split across rooms. Example: \[\{ "adults": 2 }, \{ "adults": 1, "children\_ages": \[5] }]. Do NOT combine with the shorthand fields (adults/children/rooms) — use one or the other. | | `adults` | `integer` | No | Shorthand: total adults across all rooms. Use ONLY when there is no ambiguity (1 or 2 adults = single room). For 3+ adults, or odd splits, ask the user how they want to split rooms and pass occupancies\[] instead — e.g. 4 adults → \[\{adults:2},\{adults:2}] (double + double) vs a single 4-sleeper is a meaningfully different search. If the user does not clarify, the server defaults to 2-adults-per-room (remainder in the last room), so every 4-adult request becomes two double rooms. Do NOT combine with occupancies\[] — use one or the other. | | `children` | `array` | No | Shorthand: ages of all children across all rooms. If children are present, prefer occupancies\[] so the caller controls which room each child goes in (ages affect pricing and some providers reject invalid age/room combinations). | | `rooms` | `integer` | No | Shorthand: number of rooms (BFF auto-distributes adults + children). Use when the user named a room count but not the per-room split. | | `currency` | `string` | No | ISO 4217 currency code (e.g. "EUR", "USD", "GBP", "JPY"). ALWAYS set this — omitting it falls back to USD which is rarely what users actually want. Infer from the strongest signal available: (1) the user's explicit ask ("show me prices in pounds"), (2) the conversation language/locale (French → EUR, Japanese → JPY, German → EUR, Spanish/Catalan/Italian/Portuguese → EUR, English UK → GBP, English US → USD), (3) the destination country (Italy/France/Germany → EUR, UK → GBP, Japan → JPY, US → USD). When in doubt between two plausible currencies, prefer the one matching the user's likely home country. | | `guest_nationality` | `string` | No | Guest nationality (ISO 3166-1 alpha-2, uppercase, e.g. "FR"). Affects rate availability + tax handling at search time. Separate from traveler nationality used for booking documents. | | `filters` | `object` | No | Optional filter overrides applied on top of the tenant default filter set. | | `filters.min_rating` | `number` | No | Minimum guest review rating (0-10 scale). | | `filters.min_star_rating` | `integer` | No | Minimum star rating (1-5). Pair with max\_star\_rating to bound a range. | | `filters.max_star_rating` | `integer` | No | Maximum star rating (1-5). Pair with min\_star\_rating to bound a range. | | `filters.min_reviews` | `integer` | No | Minimum number of guest reviews. | | `filters.hotel_type_ids` | `array` | No | Filter by hotel type IDs (e.g. boutique, resort). | | `filters.chain_ids` | `array` | No | Filter by hotel chain IDs (e.g. "hilton", "marriott", "accor", "ihg"). | | `filters.facility_ids` | `array` | No | Filter by facility IDs (e.g. pool, gym, spa). Applied at connector search time, not post-filtered. | | `filters.max_results` | `integer` | No | Maximum number of hotels to return per page (default 50). | | `filters.offset` | `integer` | No | Pagination offset — skip this many hotels at the upstream search (default 0). | | `trip_id` | `string` | No | Existing trip\_id to associate this search with. Unified (cart-widget) tool only — the DevPlatform variant accepts the field for schema consistency but ignores it (no widget surface). Forward whenever the user is mid-trip-build (you have seen a trip\_id in a recent trip(...) tool result and the user has NOT pivoted to a different trip context, e.g. a new origin OR destination city or unrelated request). Drop on pivot. Echoed back in the result so the cart widget can append the next selection to the same trip. | ## Examples **Simple city search, 2 adults, 3 nights in Paris:** ```json theme={null} { "name": "hotel_search", "arguments": { "destination": { "query": "Paris" }, "checkin": "2026-07-15", "checkout": "2026-07-18", "adults": 2 } } ``` **Two rooms, kids in one:** ```json theme={null} { "name": "hotel_search", "arguments": { "destination": { "city_name": "Barcelona", "country_code": "ES" }, "checkin": "2026-08-01", "checkout": "2026-08-05", "occupancies": [ { "adults": 2 }, { "adults": 1, "children_ages": [5, 7] } ] } } ``` **Near a coordinate with filters:** ```json theme={null} { "name": "hotel_search", "arguments": { "destination": { "latitude": 48.8566, "longitude": 2.3522, "radius_km": 3 }, "checkin": "2026-07-15", "checkout": "2026-07-18", "adults": 2, "filters": { "min_rating": 8, "min_star_rating": 4, "facility_ids": ["pool", "wifi"], "max_results": 20 } } } ``` Each hotel's `rooms[].rates[]` includes a `offer_id` starting with `htl_`. Pass it as a `trip_item_token` to `trip(add_item)`, hotels coexist with flight items in the same trip. # Lowest Fare Source: https://docs.gojinko.com/tools/lowest-fare Cheapest fares for a fixed route + date — up to ten itineraries, cheapest first The cheapest fares for a fixed route and date. Takes the same inputs as Flight Calendar but for one specific departure date (one-way, or with a return date for round-trip) returns up to ten itineraries sorted cheapest-first. The fixed-date counterpart of Flight Calendar — reach for it when the date is locked and you just want the cheapest options that day. Cache-backed; no live pricing. Each result includes an offer token you can pass into a live price check or directly into a trip. ```text theme={null} Find the cheapest fares for a known origin, destination, and FIXED date using cached pricing. Takes the SAME inputs as flight_calendar, but for one specific departure date (one-way, or with a return date for round-trip) it returns up to ten itineraries sorted cheapest-first. WHEN TO USE THIS TOOL: - The user knows the route AND the exact date, and just wants the cheapest options that day. - Examples: "Cheapest flight Paris → New York on June 15", "What's the lowest fare CDG→JFK on the 15th?". WHEN TO USE flight_calendar / find_dates INSTEAD: - The user is flexible on dates (a range or "when should I fly?") — use flight_calendar (full grid) or find_dates (curated date spread). WHEN TO USE flight_search INSTEAD: - The user is ready to book and needs live pricing + a bookable token. flight_search hits live pricing. IMPORTANT: All dates MUST be in the future. Never use past dates. Origin and destination must be IATA city codes by default, or IATA airport codes if the user specifies them. Use trip_type="roundtrip" with a return date for a round-trip; otherwise "oneway". Flow: lowest_fare → flight_search (price-check) → trip → book ``` ## Parameters | Name | Type | Required | Description | | ----------------------- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | | `origin` | `string` | Yes | Origin airport IATA code or city code (3 letters). Examples: "JFK", "PAR". | | `destination` | `string` | Yes | Destination airport IATA code or city code (3 letters). Examples: "CDG", "NRT". | | `trip_type` | `enum ("oneway" \| "roundtrip")` | Yes | Trip type: "oneway" or "roundtrip". | | `departure_dates` | `array` | No | Specific departure dates (YYYY-MM-DD). Multiple dates searched with OR logic. | | `departure_date_ranges` | `array` | No | Departure date ranges for flexible search. | | `return_dates` | `array` | No | Specific return dates (YYYY-MM-DD) for round-trip flights. | | `return_date_ranges` | `array` | No | Return date ranges for flexible round-trip search. | | `stay_days` | `integer` | No | Exact stay duration in days. Auto-calculates return date. | | `stay_days_range` | `object` | No | Flexible stay duration range. Example: \{min: 5, max: 10} | | `stay_days_range.min` | `integer` | Yes | Minimum stay duration in days | | `stay_days_range.max` | `integer` | Yes | Maximum stay duration in days | | `direct_only` | `boolean` | No | Only return nonstop flights. | | `cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. | | `max_total` | `number` | No | Maximum total price for the trip (canonical name). Preferred over max\_price. | | `max_price` | `number` | No | Deprecated alias for max\_total. Use max\_total instead. | | `sort_by` | `enum ("lowest" \| "recommendation")` | No | Sort order. Default: "lowest" (cheapest first). | | `currency` | `string` | No | ISO 4217 currency code. Defaults to "USD". | | `locale` | `string` | No | BCP 47 locale. Defaults to "en-US". | | `format` | `enum ("text" \| "json")` | No | Response format. "text" returns plain text for LLMs. "json" returns structured JSON. | # Overview Source: https://docs.gojinko.com/tools/overview The canonical reference for Jinko's MCP tools — what each tool does, its input schema, and examples. Connect any OAuth-capable MCP client to the remote endpoint. This is the reference for every tool the Jinko MCP server exposes. Each tool page shows its **input schema, parameters, and examples**. New here? Start with [Connect over MCP](/connect/mcp) to wire up your client, then come back for the per-tool detail. ## Endpoint | Environment | Endpoint | | ----------- | ---------------------------------------------- | | Production | `https://mcp.builders.gojinko.com/mcp` | | Sandbox | `https://mcp.builders.sandbox.gojinko.com/mcp` | Production is the default. Use **sandbox** to run the full flow against isolated data — it uses **separate API keys / OAuth** (see [Sandbox keys](/authentication/api-keys#sandbox-keys)). A production token will not authenticate against sandbox, and vice-versa. ## Authentication Most modern MCP clients connect over **OAuth** — give them the endpoint URL and approve the flow. When a client doesn't support OAuth, attach your API key as a bearer token instead: ```http theme={null} Authorization: Bearer jnk_your_key ``` See [Connect over MCP](/connect/mcp) for client-specific setup (Claude Code, Cursor, and more). ## Tools by capability Cache-backed search — `find_destination`, `flight_calendar`, `find_dates`, `lowest_fare`, `price_monitoring`. Fast; stale-within-minutes prices. Live pricing + trip building — `flight_search`, `trip`, `book`, `get_trip`. Returns bookable tokens. Live hotel search — `hotel_search`, `hotel_details`. Hotel tokens plug into the same trip as flights. Manage an order — `get_booking`, flight refund / exchange, `hotel_cancel`. # Price Monitoring Source: https://docs.gojinko.com/tools/price-monitoring Monitor price for a specific origin, destination, and dates pair Watch a specific route and date pair over time so an agent can act when the fare drops. Use it for prompts like "alert me when Paris to New York for June 17 to 26 goes under €400". Each response includes the current cheapest cached fare and an offer token you can pass to flight\_search when the user decides to book. Cache-only; never triggers a live call. ```text theme={null} Cache-only flight price snapshot for a fixed origin/destination + dates pair. Intended for scheduled polling — NOT for one-shot shopping or booking. WHEN TO USE: - Track the price of a specific route + dates over time and react when it drops (cron / scheduled job). - Recommended cadence: poll no faster than the cache refresh interval. Polling faster is wasted work. WHAT IT RETURNS: - The single cheapest cached itinerary matching the request filters (lowest WITHIN the filter constraints — filters constrain the candidate set, not the win condition). - An offer_token that remains re-shoppable via flight_search (price_check mode) when the user decides to book. - status: "ok" (offer present) or "stale" (cache had no matching itinerary — retry later, or call flight_search for a live quote). WHEN TO USE flight_search INSTEAD: - The user is ready to book NOW and needs a live quote. - One-shot exploration where you don't intend to come back. WHEN TO USE flight_calendar / find_destination INSTEAD: - Flexible dates or ranges — price_monitoring requires exact departure_date (+ optional exact return_date). - The user is still exploring and hasn't committed to a specific route to monitor. CACHE-ONLY CONTRACT: - This tool NEVER triggers a live connector call. status:"stale" is the correct response when the cache is cold — do not retry in a tight loop and do not silently fall back to flight_search. INPUT NOTES: - Origin / destination: IATA city code preferred (PAR, NYC, LON); pin to airport only when the user actually committed to a specific airport. - Use the SAME filter set the user has been monitoring against between polls. ``` ## Parameters | Name | Type | Required | Description | | -------------------------- | ---------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `origin` | `string` | Yes | Origin IATA city code (e.g. PAR, NYC, LON) or airport code (CDG, JFK, LHR). City codes preferred — they cover every airport in the city. | | `origin_type` | `enum ("city" \| "airport")` | No | How to interpret origin. "city" (default) searches all airports in the city; "airport" pins to one airport. | | `destination` | `string` | Yes | Destination IATA city code (e.g. MIL, BCN, TYO) or airport code (MXP, BCN, NRT). City codes preferred. | | `destination_type` | `enum ("city" \| "airport")` | No | How to interpret destination. Same semantics as origin\_type. | | `departure_date` | `string` | Yes | Single departure date (YYYY-MM-DD). Exactly one date — no arrays or ranges. | | `return_date` | `string` | No | Single return date (YYYY-MM-DD). Omit for one-way. Must be on or after departure\_date. | | `direct_only` | `boolean` | No | If true, only return non-stop flights. Mirror the upstream filter the user committed to when they started monitoring. | | `cabin_class` | `enum ("economy" \| "premium_economy" \| "business" \| "first")` | No | Cabin class filter. Omit for economy. | | `max_price` | `number` | No | Upper bound on the total fare in the requested currency. Lowest-fare semantics are "lowest within the filter constraints" — max\_price tightens the candidate set, not the win condition. | | `include_carriers` | `array` | No | IATA 2-letter marketing carrier codes to include (whitelist). Example: \["AF","KL"]. Use to lock monitoring to specific airlines the user actually flies. | | `exclude_carriers` | `array` | No | IATA 2-letter marketing carrier codes to exclude (blacklist). Example: \["FR","U2"]. Use to keep airlines the user refuses out of the picture. | | `traveler_counts` | `object` | No | Traveler counts. Defaults to 1 adult. | | `traveler_counts.adults` | `integer` | No | Number of adult travelers (12+). | | `traveler_counts.children` | `integer` | No | Number of child travelers (2-11). | | `traveler_counts.infants` | `integer` | No | Number of infant travelers (under 2). | | `locale` | `string` | No | User's BCP 47 locale (e.g. "fr-FR", "en-US"). Inherits from the conversation locale if omitted. | | `currency` | `string` | No | ISO 4217 currency code (e.g. "EUR", "USD"). Inherits from the conversation if omitted. Must match the currency the user is monitoring against — switching currencies mid-poll is not what they want. | ## Examples **Daily poll of PAR → NYC for a date pair:** ```json theme={null} { "name": "price_monitoring", "arguments": { "origin": "PAR", "destination": "NYC", "departure_date": "2026-06-17", "return_date": "2026-06-26", "currency": "EUR" } } ``` **Constrained poll — direct-only, economy, under €800, Air France or KLM only:** ```json theme={null} { "name": "price_monitoring", "arguments": { "origin": "PAR", "destination": "NYC", "departure_date": "2026-06-17", "return_date": "2026-06-26", "direct_only": true, "cabin_class": "economy", "max_price": 800, "include_carriers": ["AF", "KL"], "currency": "EUR" } } ``` The returned `offer_token` is directly re-shoppable via `flight_search` (price\_check mode) when the user is ready to book. # Trip Source: https://docs.gojinko.com/tools/trip Create and manage a trip — add or remove items, set travelers, select ancillaries Assemble and edit a trip before sending it to checkout. Use it to add a flight or hotel offer, set traveler details, swap one item for another, or attach ancillaries like bags and seats. Flights and hotels can sit side by side in the same trip and settle through a single checkout. ```text theme={null} Create and manage a trip: add flight or hotel items, remove items, set traveler details, and select ancillaries. Operations: - add_item: Add a flight or hotel to the trip. Pass trip_item_token from flight_search (offer__* tokens) or offer_id from hotel_search (htl_* tokens). Omit trip_id to create a new trip. - remove_item: Remove an existing item from the trip by item_id (from trip response items[].item_id). Requires an existing trip_id. Can be combined with add_item in a single call to swap an item — remove runs first, then add. - upsert_travelers: Set traveler details and contact info on an existing trip_id. - select_ancillaries: Select bags, seats, meals for a quoted trip item. Requires trip_id and item_id. Returns trip_id for use with the book tool. Flights and hotels can coexist in the same trip (single Stripe checkout). IMPORTANT — TRAVELER DATA: NEVER invent or fabricate traveler data. Before calling upsert_travelers, you MUST ask the user for ALL required fields: - first_name, last_name, date_of_birth (YYYY-MM-DD), gender (male/female) - Contact: email, phone (with country code) If ANY field is missing, ASK the user. Do not use placeholder or default values. ANCILLARY FLOW: After adding an item and setting travelers, check trip response for available_ancillaries on trip items. If ancillaries are available, offer them to the user before proceeding to book. Use select_ancillaries with the offer_ids from available_ancillaries. Full replacement semantics — send all desired selections. Flows: - Flights: flight_calendar → flight_search → trip(add_item) → trip(upsert_travelers) → [trip(select_ancillaries)] → book - Hotels: hotel_search → trip(add_item) → trip(upsert_travelers) → book - Mixed: both in the same trip — one cart, one checkout ``` ## Parameters | Name | Type | Required | Description | | ------------------------------- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `trip_id` | `string` | No | Existing trip ID. Omit to create a new trip. | | `add_item` | `object` | No | Add a flight or hotel item to the trip. | | `add_item.trip_item_token` | `string` | Yes | Token from flight\_search results (offer\_\_\* format) or offer\_id from hotel\_search results (htl\_\* format). | | `remove_item` | `object` | No | Remove an existing item from the trip. Requires an existing trip\_id — you cannot remove from a trip that has not been created yet. Can be combined with add\_item in a single call to swap an item (remove runs first, then add). | | `remove_item.item_id` | `string` | Yes | ID of the trip item to remove. Matches the value returned in the trip response items\[].item\_id field. | | `upsert_travelers` | `object` | No | Set or update travelers and contact info on the trip. Optional per call (you can add\_item while building the cart), but travelers and a contact must be present before booking. | | `upsert_travelers.travelers` | `array` | Yes | List of travelers (replaces all). Required to complete a booking; the first traveler also supplies the booking contact name. | | `upsert_travelers.contact` | `object` | Yes | Booking contact (email + phone, both required). Required before the trip can be booked. | | `select_ancillaries` | `object` | No | Select ancillaries (bags, seats, meals) for a quoted trip item. Uses full-replacement semantics — send all desired selections. | | `select_ancillaries.item_id` | `string` | Yes | ID of the trip item to select ancillaries for. Get from trip response trip\_items\[].id | | `select_ancillaries.selections` | `array` | Yes | Ancillary selections. Full replacement — send all desired selections each time. Get offer\_ids from trip\_item.available\_ancillaries\[].offer\_id | ## Examples **Create a new trip (add flight + set travelers in one call):** ```json theme={null} { "name": "trip", "arguments": { "add_item": { "trip_item_token": "offer_abc123:fare_xyz" }, "upsert_travelers": { "travelers": [ { "first_name": "Jane", "last_name": "Doe", "date_of_birth": "1990-01-15", "gender": "FEMALE", "passenger_type": "ADULT", "frequent_flyer": { "airline": "LH", "number": "992100100" } } ], "contact": { "email": "jane@example.com", "phone": "+33612345678" } } } } ``` **Add a hotel to an existing trip:** ```json theme={null} { "name": "trip", "arguments": { "trip_id": "42", "add_item": { "trip_item_token": "htl_abc..." } } } ``` **Update travelers only (no new items):** ```json theme={null} { "name": "trip", "arguments": { "trip_id": "42", "upsert_travelers": { "travelers": [ { "first_name": "Jane", "last_name": "Doe", "date_of_birth": "1990-01-15", "gender": "FEMALE", "passenger_type": "ADULT", "frequent_flyer": { "airline": "LH", "number": "992100100" } }, { "first_name": "John", "last_name": "Doe", "date_of_birth": "2015-05-20", "gender": "MALE", "passenger_type": "CHILD" } ], "contact": { "email": "jane@example.com", "phone": "+33612345678" } } } } ``` **Add a frequent-flyer number:** Each traveler can carry an optional `frequent_flyer` object so miles are credited on the booking. `airline` is the IATA code of the **program issuer** (e.g. `LH` for Lufthansa Miles & More) — not necessarily the operating carrier, since alliances credit miles on partner flights. Both `airline` and `number` are required when the object is present. ```json theme={null} { "name": "trip", "arguments": { "trip_id": "42", "upsert_travelers": { "travelers": [ { "first_name": "Jane", "last_name": "Doe", "date_of_birth": "1990-01-15", "gender": "FEMALE", "passenger_type": "ADULT", "frequent_flyer": { "airline": "LH", "number": "992100100" } } ] } } } ``` Traveler details must match real travel documents, airlines enforce name / DOB matching and reject bookings where they don't. Never let an agent fabricate these. The response includes `trip_id`, the current item list, and totals. Use `trip_id` with `book` when you're ready to check out.