Skip to content Documentation index for agents (llms.txt)
Glotto Beta
Get started

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

npm install @your-org/petstore
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 Errors — 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.

Cursor pagination

List methods return an async iteratorfor 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.

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.

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.

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.

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, 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 for precedence and cancellation.

Binary downloads 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.