# TypeScript SDK

> The faxforagents package for Node and TypeScript, on npm since 2026-10-30: upload, quote, send, wait for the receipt, list jobs. The REST calls work without it.

Page: https://faxforagents.com/docs/sdks/typescript/
Last changed: 2026-10-30

Updated Oct 30, 2026

The npm package is named `faxforagents` and has been on npm since 2026-10-30. Install it with `npm install faxforagents`. Node 18 or later, Deno, Bun, browsers and edge runtimes, no runtime dependencies. The REST calls further down work with `fetch` as well, so nothing here depends on the package.

## Status

Published. The package is generated from the same OpenAPI document as this site, built with tsup and published with npm provenance. The quickstart below is the one from the package's README. The package page is [npmjs.com/package/faxforagents](https://www.npmjs.com/package/faxforagents). The MCP bridge for stdio clients will be `faxforagents-mcp`. The sources are at [github.com/faxforagents/sdk-typescript](https://github.com/faxforagents/sdk-typescript) and [github.com/faxforagents/mcp](https://github.com/faxforagents/mcp).

## Install and send with the package

Shell

```
`npm install faxforagents`
```

TypeScript

```
`import { FaxForAgents } from 'faxforagents'; const ffa = new FaxForAgents(); // reads FAXFORAGENTS_API_KEY const doc = await ffa.documents.create({ text: 'Hello from an agent.', filename: 'hello' }); console.log(doc.id, doc.page_count, doc.sha256.slice(0, 12)); const quote = await ffa.quotes.create({ document_id: doc.id, to: '+15550000001' }); console.log(quote.amount_micro, 'micro, expires', quote.expires_at); let fax = await ffa.faxes.create({ quote_id: quote.id }); // Idempotency-Key minted for you console.log(fax.id, fax.state); // queued, never delivered yet fax = await ffa.faxes.wait(fax.id); // polls until a terminal state console.log(fax.state, fax.pages_sent, fax.evidence); // delivered, 1, {...} for await (const job of ffa.faxes.iter({ state: 'failed' })) { // follows next_cursor console.log(job.id, job.failure_code); }`
```

A test key is tied to the sandbox, where the destination number picks the outcome. ESM and CommonJS builds, types included.

## Send a fax with fetch

TypeScript

```
`const API = 'https://api.faxforagents.com/v1' const KEY = process.env.FFA_KEY! // ffa_test_..., never in source control async function call<T>(path: string, init: RequestInit = {}): Promise<T> { const r = await fetch(API + path, { ...init, headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json', ...init.headers } }) if (!r.ok) throw new Error(`${r.status} ${await r.text()}`) return r.json() as Promise<T> } const doc = await call<{ id: string }>('/documents', { method: 'POST', body: JSON.stringify({ markdown: '# PO 4411\n\nPlease confirm.' }) }) const quote = await call<{ id: string }>('/fax-quotes', { method: 'POST', body: JSON.stringify({ document_id: doc.id, to: '+15550000001' }) }) const job = await call<{ id: string; state: string }>('/faxes', { method: 'POST', headers: { 'Idempotency-Key': 'po-4411' }, body: JSON.stringify({ quote_id: quote.id }) }) console.log(job.id, job.state) // fax_..., queued`
```

## Upload a PDF

TypeScript

```
`import { readFile, stat } from 'node:fs/promises' const size = (await stat(file)).size const up = await call<{ id: string; upload_url: string }>('/uploads', { method: 'POST', body: JSON.stringify({ filename: 'contract.pdf', size_bytes: size }) }) await fetch(up.upload_url, { method: 'PUT', body: await readFile(file) }) await call(`/uploads/${up.id}/complete`, { method: 'POST' }) const doc = await call<{ id: string }>('/documents', { method: 'POST', body: JSON.stringify({ upload_id: up.id }) })`
```

## How do I page through jobs?

TypeScript

```
`let cursor: string | undefined do { const page = await call<{ items: { id: string; state: string }[]; next_cursor?: string }>(`/faxes?limit=50${cursor ? `&cursor=${cursor}` : ''}`) for (const job of page.items) console.log(job.id, job.state) cursor = page.next_cursor } while (cursor)`
```

## How do I verify a webhook?

The reference verifier is on the [webhooks page](https://faxforagents.com/docs/webhooks/). The package ships the same function as `verifyWebhook`.

## Errors

Every non-2xx body is the error envelope. Read `error.code` and `error.retryable`. Retry a retryable call with the same `Idempotency-Key`. The [errors page](https://faxforagents.com/docs/errors/) lists every code.
