Private betav0.1.0
Docs
Format developer documentation

Overview

The Format render API accepts HTML and assets, and returns a PDF.

The Format API renders PDFs from HTML. You send a POST request with your rendered HTML and an optional assets ZIP, and receive a PDF binary stream in response.

Base URL

https://api.format.dev

Authentication

All requests require a FORMAT_API_KEY passed as a Bearer token.

Authorization: Bearer {FORMAT_API_KEY}

You can create and manage API keys from the Format dashboard.

Render a PDF

POST /v1/render
Content-Type: multipart/form-data

Request fields

FieldTypeRequiredDescription
htmlstringYesRendered HTML output from a compiled Format template
assetsfileNoZIP file containing images, fonts, and other static resources referenced by the HTML
tagsstringNoJSON array of string tags for filtering and analytics in the dashboard

Response

A successful response returns the PDF as a binary stream.

HeaderValue
Content-Typeapplication/pdf
Content-Dispositionattachment; filename="document.pdf"
Content-LengthSize in bytes

Example with cURL

curl -X POST https://api.format.dev/v1/render \
  -H "Authorization: Bearer $FORMAT_API_KEY" \
  -F "html=<rendered-html.txt" \
  -F "[email protected]"

Example with Node.js

The @format.dev/client package handles multipart encoding, streaming, and error handling.

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')
}

Document versions

The Format SDKs and format compile write two attributes onto every document they produce:

<template data-type="document" data-sdk="0.2.0" data-engine="0.1.0">

data-sdk is the Format release that produced the document. data-engine is the engine it renders on — Format serves that exact version, so the document renders the same way whenever you send it.

<Document> writes both from constants inlined when its package was built. There is no prop for either, and nothing in your document can change them — they record which build produced it.

If the two disagree

A document that names a Format release has to name that release's engine. If it names a different one, it was built from two releases at once, and Format refuses it:

{
  "error": {
    "code": "SDK_ENGINE_TARGET_MISMATCH",
    "message": "This document says it was produced by Format 0.2.0, which targets engine 0.1.0, but it asks for engine 0.9.9."
  }
}

Run format update to bring your installed packages into line, then rebuild the document.

Hand-authored HTML

You can write the document model by hand. Hand-written HTML has no data-sdk since there is no HTML SDK release to check against.

You do have to set data-engine yourself. Format has no default engine, and refuses a document that does not name one.

Run that HTML through format compile and it comes out with a data-sdk, naming compile's own release. From then on Format checks it like any other document.

Errors

The API returns JSON error bodies for non-2xx responses.

{
  "error": "invalid_request",
  "message": "The html field is required"
}
StatusMeaning
400Bad request. Missing or invalid fields, or a document whose data-sdk and data-engine name different releases.
401Unauthorized. Invalid or missing API key.
413Payload too large. HTML or assets exceed the size limit.
429Rate limited. Too many requests.
500Internal server error.

Timeouts

The API enforces a render timeout per request. If your document takes too long to render, the request returns a 504 status. The default timeout for the @format.dev/client is 120 seconds.

Content limits

LimitValue
HTML body10 MB
Assets ZIP50 MB
Total request60 MB

Next steps

  • API client for the full Node.js and browser client reference
  • Compile to produce renderer bundles and asset ZIPs
  • Deployment for production integration patterns
Was this page helpful?