TypeScript SDK
Updated
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. The MCP bridge for stdio clients will be faxforagents-mcp. The sources are at github.com/faxforagents/sdk-typescript and github.com/faxforagents/mcp.
Install and send with the package
npm install faxforagents 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);
} Send a fax with fetch
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
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?
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. 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 lists every code.