> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dev.gojinko.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript 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.

<Note>
  **`@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.
</Note>

## 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:

<Steps>
  <Step title="Explicit apiKey option">
    ```typescript theme={null}
    createJinkoClient({ apiKey: 'jnk_...' })
    ```
  </Step>

  <Step title="JINKO_API_KEY env var">
    ```bash theme={null}
    export JINKO_API_KEY=jnk_...
    ```

    ```typescript theme={null}
    createJinkoClient() // picks up env
    ```
  </Step>

  <Step title="~/.jinko/config.yaml (CLI-shared)">
    The same config file the [CLI](/connect/cli) uses. Run `jinko auth login` to populate it; your scripts pick it up automatically.
  </Step>
</Steps>

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.

<Note>
  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.
</Note>

## 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) via `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.checkout(tripId)`                                                                         | Schedule checkout, get Stripe URL + `agent_spt_params`                                                                    |
| `client.submitAgentPayment(tripId, token)`                                                        | Agentic pay: redeem a Shared Payment Token to authorize the booking                                                       |
| `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.destination(req)` / `market(req)` / `audience(req)`                                       | Travel demand rankings by share: top destinations, source markets, traveler audiences                                     |
| `client.destinationTrend(req)` / `marketTrend(req)` / `audienceTrend(req)` / `trend(req)`         | Travel demand time series: destination, market, and audience trends, plus explicit origin and destination pairs (`trend`) |
| `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

<CardGroup cols={2}>
  <Card title="Booking guide" icon="plane" href="/guides/flight-booking">
    End-to-end booking flow in TypeScript, CLI, and MCP.
  </Card>

  <Card title="API reference" icon="cloud" href="/api-reference/introduction">
    Per-endpoint docs with SDK / CLI / curl samples.
  </Card>

  <Card title="Authentication" icon="key" href="/authentication/api-keys">
    API keys, OAuth flows, and when to use each.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/concepts/errors">
    Status codes, error envelope, and debugging.
  </Card>
</CardGroup>
