> For the complete documentation index, see [llms.txt](/llms.txt)

# TypeScript

The TypeScript SDK is Glotto's reference target — a typed, tree-shakable client emitted from
the same `GlottoIR` as every other language. It ships as an ESM-first npm package with a
self-building manifest, so `npm install` then `import { Client }` is all it takes.

## Quickstart

```bash
npm install @your-org/petstore
```

```ts
import { Client } from '@your-org/petstore';

const client = new Client({ token: process.env.PETSTORE_TOKEN });

// a single call
const pet = await client.pets.createPet({ name: 'Rex' });

// pagination is an async iterator — `for await` walks every page
for await (const pet of client.pets.listPets()) {
  console.log(pet.name);
}
```

## Typed errors

Non-2xx responses reject with typed error classes, not bare `Error`s — the status family
maps to a class (`BadRequestError`, `RateLimitError`, …) and the parsed response body is
typed from the spec's error schema, so you can `catch` and narrow. See [Errors](/docs/errors).

## Cursor pagination

List methods return an **async iterator** — `for await` walks every page, with the generated
method advancing the cursor for you. Glotto emits the right walker for the API's strategy
(cursor, page, offset, or link-header). See [Pagination](/docs/pagination).

## Retries & backoff

Transient failures (`5xx`, `429`, transport errors) retry with exponential backoff and jitter;
non-idempotent writes only retry when idempotency is enabled. Tune `maxAttempts`,
`initialDelayMs`, `maxDelayMs`, and `jitter` per client. See [Retries & timeouts](/docs/retries).

## SSE streaming

Server-sent-event endpoints return an async iterator of typed events, decoded from the
`text/event-stream` framing — `for await (const event of client.…())`. A frame whose payload
isn't valid JSON surfaces a parse error to your loop (never a raw string mistyped as your
model); declare terminal sentinels like `data: [DONE]` via `streaming.on_event`. See
[Streaming](/docs/streaming).

## Unknown response fields

Your API can add a response field without it being a breaking change — but a generated interface gives you no typed way to reach it. The generated
models keep it instead: a field the SDK wasn't generated from is retained on decode, readable
through an accessor, and written back out when the model is re-serialized.

```ts
const pet = await client.pets.createPet(body);

// A field your API started returning after this SDK was generated.
const extra = petExtraFields(pet);
if ('species' in extra) {
  console.log(extra.species);
}
```

Each model gets its own reader — `petExtraFields(pet)`, `tagExtraFields(tag)` — typed to that
model, so passing the wrong one is a compile error rather than an empty object at runtime.

The runtime keeps the data regardless: the decode is a cast, so the extra keys are already on
the object and `JSON.stringify` writes them back. The readers are what make them *reachable* —
without one you would need an unchecked cast, and nothing would stop a future change from dropping
them. An index signature was deliberately not used: these same interfaces type your request bodies,
and `[key: string]: unknown` would switch off excess-property checking across the whole SDK.

The retained fields are read-only by design. To *send* a field your spec doesn't model yet, use the
per-call extra-body escape hatch rather than writing to the retained bag.

## File uploads

`multipart/form-data` operations accept platform file types (`Blob`/`File`/streams) and the
client builds the multipart body, so binary uploads work without hand-assembling form parts.

## Pages, request controls, and files

Paginated methods also expose [manual pages](/docs/pagination#fetch-one-page),
so you can inspect one response and request its successor explicitly. Request
overrides apply to the initial call and to each requested next page; see
[Retries & timeouts](/docs/retries) for precedence and cancellation.

[Binary downloads](/docs/file-transfers) return an owned byte response with
metadata, a bounded read helper, and incremental consumption. Close the response
when you stop early. Your generated README demonstrates these operations with
your API's names and the language's native calling conventions.
