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

# TypeScript SDK

> @inkrelay/sdk for Node 18 and later.

The TypeScript SDK wraps the REST API with typed methods, automatic retries on 429 and 5xx responses, automatic idempotency keys for print jobs, pagination iterators and webhook verification.

```bash theme={null}
npm install @inkrelay/sdk
```

```ts theme={null}
import { InkRelay } from "@inkrelay/sdk";

const ir = new InkRelay({ apiKey: process.env.INKRELAY_API_KEY });

for await (const printer of ir.printers.iterate()) console.log(printer.id);

const job = await ir.printJobs.createAndWait(
  { printerId, title: "Invoice", contentType: "pdf_uri", content: url },
  { timeoutMs: 60_000 },
);
console.log(job.state);
```

`createAndWait` creates the job and polls until it reaches `done`, `error`, `cancelled` or `expired`. It returns the final job, so check `job.state` and `job.stateMessage` rather than expecting an exception for a failed print.

## Configuration

```ts theme={null}
const ir = new InkRelay({
  apiKey: "ir_test_...", // defaults to process.env.INKRELAY_API_KEY
  baseUrl: "https://api.inkrelay.app", // the default
  maxRetries: 3, // the default
});
```

| Option | Default | Meaning |
| - | - | - |
| `apiKey` | `INKRELAY_API_KEY` | Your `ir_test_` or `ir_live_` key. The constructor throws if neither is set |
| `baseUrl` | `https://api.inkrelay.app` | Override for a proxy or a local server |
| `maxRetries` | `3` | Retries after the first attempt |

The SDK retries `429` responses, waiting for `Retry-After` when it is present, and retries `5xx` responses and network errors with exponential backoff. `printJobs.create` and `createAndWait` send an `Idempotency-Key` automatically and reuse it on every retry, so a retry cannot print twice. Pass `{ idempotencyKey }` as the second argument to use your own key. Other `POST` requests are not retried on `5xx` errors.

## Errors

Any non-2xx response that survives the retries throws an `InkRelayError` with `status`, `code` and `requestId`. `createAndWait` throws an `InkRelayTimeoutError` when the job is still not in a final state after `timeoutMs` (default 60 seconds); its `job` property holds the last known job, which may still print.

```ts theme={null}
import { InkRelay, InkRelayError, InkRelayTimeoutError } from "@inkrelay/sdk";

try {
  await ir.printJobs.createAndWait({ printerId, title: "Invoice", contentType: "pdf_uri", content: url });
} catch (err) {
  if (err instanceof InkRelayTimeoutError) console.warn("still not done", err.job.id, err.job.state);
  else if (err instanceof InkRelayError) console.error(err.status, err.code, err.requestId);
  else throw err;
}
```

See [Errors](/guides/errors) for the codes the API returns.

## Pagination

`list(params)` returns one page, `{ data, hasMore, nextCursor }`. `iterate(params)` is an async generator that follows `nextCursor` for you and yields every item:

```ts theme={null}
const page = await ir.printJobs.list({ limit: 50, state: "error" });
console.log(page.data.length, page.hasMore, page.nextCursor);

for await (const job of ir.printJobs.iterate({ state: "error" })) console.log(job.id, job.stateMessage);
```

`computers`, `printers`, `printJobs` and `webhooks` have `list`, `iterate` and `get`. `events` (and webhook deliveries) have `list` and `iterate` only, with no `get`. Pass `after` and `dir: "asc"` to `events.list` to poll for new events.

## Webhooks

`ir.webhooks.verify(body, headers, secret)` checks the signature of a request and throws `WebhookVerificationError` if it is invalid or older than 5 minutes. Pass the raw body string, not parsed JSON.

```ts theme={null}
ir.webhooks.verify(rawBody, req.headers, process.env.INKRELAY_WEBHOOK_SECRET!);
```

The same object manages endpoints: `ir.webhooks.create`, `update`, `delete`, `deliveries(id)` and `replay(deliveryId)`. `create` returns the signing secret once. See [Webhooks](/guides/webhooks) for a full receiver.

## Raw generated client

The convenience methods sit on top of a client generated from the OpenAPI spec. It has one function per operation, named by its operationId, and a type for every schema:

```ts theme={null}
import { raw } from "@inkrelay/sdk";
```

Use it for an endpoint the wrapper has no helper for. The generated functions do not add retries or idempotency keys.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.