Private betav0.1.0
Docs
Format developer documentation

API client

Node.js and browser client for rendering PDFs with the Format API.

The @format.dev/client package provides a typed client for the Format render API. It handles multipart uploads, streaming responses and timeouts.

Installation

npm install "@format.dev/client"
pnpm add "@format.dev/client"
yarn add "@format.dev/client"
bun add "@format.dev/client"

Usage

Assuming you have your compiled renderer located at ./_generated and your Format API key is in your environment variables as FORMAT_API_KEY:

import { FormatClient } from '@format.dev/client'
import { invoice } from './_generated'

const format = new FormatClient()
const doc = await invoice.render({ customerName: 'Ada Lovelace' })

const response = await format.pdf(doc)

if (response.isPdf) {
	await response.toFile('./output/invoice.pdf')
}
import { FormatClient } from '@format.dev/client'
import { invoice } from './_generated'

invoice.setAssetsUrl('https://cdn.example.com/invoice/assets.zip')

const format = new FormatClient()
const doc = await invoice.render({ customerName: 'Ada Lovelace' })

const response = await format.pdf(doc)

if (response.isPdf) {
	// Option 1: Download as file
	const blob = await response.blob()
	const url = URL.createObjectURL(blob)
	const a = document.createElement('a')
	a.href = url
	a.download = response.filename ?? 'document.pdf'
	a.click()
	URL.revokeObjectURL(url)

	// Option 2: Open in new tab
	window.open(URL.createObjectURL(await response.blob()))

	// Option 3: Embed in iframe
	const iframe = document.getElementById('preview') as HTMLIFrameElement
	iframe.src = URL.createObjectURL(await response.blob())
}

Client options

Passed to the FormatClient constructor.

NameTypeDescription
stringYour Format API key. If not provided, the client reads from the FORMAT_API_KEY environment variable.
numberMaximum time in milliseconds allowed for the render to complete. Prevents long-running renders from hanging indefinitely.

apiKey

Description
Your Format API key. If not provided, the client reads from the FORMAT_API_KEY environment variable.
Type
string

renderTimeoutMs

Description
Maximum time in milliseconds allowed for the render to complete. Prevents long-running renders from hanging indefinitely.
Type
number
Default value
120000

pdf() parameters

The first argument is a FormatDocument returned by renderer.render(). The optional second argument accepts additional options.

NameDescription
Override the document's assets stream. Use this when you build the assets zip at runtime instead of relying on the compile-time output.
Metadata tags attached to this render. Useful for filtering and analytics in the Format dashboard. Duplicate and empty tags are removed automatically.
Abort signal to cancel the request. Combined with the client's renderTimeoutMs — whichever fires first wins.

assets

Description
Override the document's assets stream. Use this when you build the assets zip at runtime instead of relying on the compile-time output.
Type
Blob | Buffer<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | ArrayBuffer | Readable | ReadStream | ReadableStream<Uint8Array<ArrayBufferLike>>
Example
fs.createReadStream('./assets.zip')

tags

Description
Metadata tags attached to this render. Useful for filtering and analytics in the Format dashboard. Duplicate and empty tags are removed automatically.
Type
string[]
Example
['invoice', 'customer-123']

signal

Description
Abort signal to cancel the request. Combined with the client's renderTimeoutMs — whichever fires first wins.
Type
AbortSignal

Response

FormatResponse extends the standard Response with additional properties extracted from the API response headers.

NameDescription
Whether the response is a PDF. Derived from contentType === 'application/pdf'.
Save the PDF stream directly to a file. Creates parent directories if they don't exist.
Suggested filename from the Content-Disposition header, if present.
Size of the PDF in bytes, from the Content-Length header. Only present on successful PDF responses.
MIME type of the response. application/pdf for successful renders, application/json for errors.
Traceparent ID for distributed tracing, if returned by the API. Useful for correlating client and server logs.

isPdf

Description
Whether the response is a PDF. Derived from contentType === 'application/pdf'.
Type
boolean

toFile

node
Description
Save the PDF stream directly to a file. Creates parent directories if they don't exist.
Type
(filePath: string, options?: WriteStreamOptions) => Promise<{ path: string; bytes: number; }>
Example
await response.toFile('./output/invoice.pdf')

filename

Description
Suggested filename from the Content-Disposition header, if present.
Type
string
Example
'document.pdf'

contentLength

Description
Size of the PDF in bytes, from the Content-Length header. Only present on successful PDF responses.
Type
number

contentType

Description
MIME type of the response. application/pdf for successful renders, application/json for errors.
Type
string

traceparent

Description
Traceparent ID for distributed tracing, if returned by the API. Useful for correlating client and server logs.
Type
string

Error handling

The client throws a FormatError when the API returns a non-2xx status code. The error includes the HTTP status and parsed response body.

NameDescription
HTTP status code from the API response.
Parsed error response body. Typically a JSON object with error details, or { raw: string } if the body couldn't be parsed.

status

Description
HTTP status code from the API response.
Type
number

detail

Description
Parsed error response body. Typically a JSON object with error details, or { raw: string } if the body couldn't be parsed.
Type
unknown
import { FormatClient, FormatError } from '@format.dev/client'
import { invoice } from './_generated'

const format = new FormatClient()

try {
  const doc = await invoice.render({ customerName: 'Ada Lovelace' })
  await format.pdf(doc)
} catch (err) {
  if (err instanceof FormatError) {
    console.error(err.status) // 400, 401, 429, 500, ...
    console.error(err.detail) // { error, message, location } on parse errors
  }
}

Parsing errors

When the API rejects a document for being malformed, status is 400 and detail carries a stable error code:

catch (err) {
  if (err instanceof FormatError && err.status === 400) {
    const { error, message, location } = err.detail as {
      error: string
      message: string
      location?: string
    }
    switch (error) {
      case 'INVALID_LAYOUT':
        // missing data-id / data-width / data-height, fix the template
        break
      case 'INVALID_ASSET_REFERENCE':
        // path doesn't match any file in assets.zip
        break
    }
  }
}

See Errors for the full list of codes and how to fix each one.

Timeouts and cancellation

The client applies a render timeout (default: 120 seconds) to every request. You can also pass your own AbortSignal, whichever fires first cancels the request.

const controller = new AbortController()

const doc = await invoice.render({ customerName: 'Ada Lovelace' })
const response = await format.pdf(doc, { signal: controller.signal })

// Cancel from elsewhere:
controller.abort()
Was this page helpful?