REST API · OpenAPI 3.1 · SDKs available

The PDF generation API developers love

One HTTP call. JSON in. Pixel-perfect PDF out in milliseconds. Generate invoices, contracts, reports — at any scale.

Get Your API Key Free → View Full Swagger Docs →

QUICKSTART
Your first PDF in 60 seconds
No SDK required. Send a JSON POST request with your template ID and data. Get a PDF binary or URL back instantly.
# Generate an invoice PDF — returns binary PDF curl https://api.typsetter.dev/v1/render \ -H "Authorization: Bearer ts_live_sk_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "template": "invoice-professional", "format": "pdf", "data": { "invoice_number": "INV-2026-001", "company_name": "Acme Corp", "client_name": "Client Ltd", "issue_date": "2026-02-21", "due_date": "2026-03-21", "items": [ { "description": "API Integration", "quantity": 1, "unit_price": 3500 }, { "description": "Consulting", "quantity": 8, "unit_price": 150 } ], "subtotal": 4700, "tax": 470, "total": 5170, "currency": "USD" } }' \ --output invoice.pdf # → 200 OK — invoice.pdf saved (PDF binary, 47KB, rendered in 312ms)
// Node.js — native fetch (Node 18+) or node-fetch import { writeFileSync } from 'fs'; const response = await fetch('https://api.typsetter.dev/v1/render', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.TYPSETTER_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ template: 'invoice-professional', format: 'pdf', data: { invoice_number: 'INV-2026-001', company_name: 'Acme Corp', items: [{ description: 'API Work', quantity: 1, unit_price: 3500 }], total: 3500, currency: 'USD' } }) }); if (!response.ok) throw new Error(`API error: ${response.status}`); const buffer = await response.arrayBuffer(); writeFileSync('invoice.pdf', Buffer.from(buffer)); console.log('PDF saved as invoice.pdf'); // Or use the official Node.js SDK: npm install @typsetter/node
# Python — requests library import requests, os response = requests.post( 'https://api.typsetter.dev/v1/render', headers={ 'Authorization': f'Bearer {os.environ["TYPSETTER_API_KEY"]}', 'Content-Type': 'application/json', }, json={ 'template': 'invoice-professional', 'format': 'pdf', 'data': { 'invoice_number': 'INV-2026-001', 'company_name': 'Acme Corp', 'client_name': 'Client Ltd', 'total': 5170, 'currency': 'USD', } } ) response.raise_for_status() with open('invoice.pdf', 'wb') as f: f.write(response.content) print(f'PDF saved ({len(response.content)} bytes)')
<?php // PHP — cURL extension $apiKey = getenv('TYPSETTER_API_KEY'); $payload = [ 'template' => 'invoice-professional', 'format' => 'pdf', 'data' => [ 'invoice_number' => 'INV-2026-001', 'company_name' => 'Acme Corp', 'total' => 5170, 'currency' => 'USD', ] ]; $ch = curl_init('https://api.typsetter.dev/v1/render'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer $apiKey", 'Content-Type: application/json', ], ]); $pdf = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code === 200) { file_put_contents('invoice.pdf', $pdf); echo "PDF saved successfully\n"; }

AUTHENTICATION
Bearer token authentication
All API requests are authenticated using Bearer tokens. Generate and manage API keys from your dashboard.
🔑

API Keys

Create multiple API keys per account — one per environment or service. Keys are prefixed with ts_live_sk_ (production) or ts_test_sk_ (sandbox). Revoke keys instantly from the dashboard.

🔒

HTTPS Only

All API requests must use HTTPS. HTTP requests are rejected with a 301 redirect. TLS 1.2+ is required. API keys in request headers are never logged or stored in our infrastructure after authentication.

Authorization header format
# All requests require this header Authorization: Bearer ts_live_sk_your_api_key_here # Test environment (sandbox, no real PDFs produced in billing) Authorization: Bearer ts_test_sk_your_test_key

ENDPOINTS
API reference
Base URL: https://api.typsetter.dev
Method Endpoint Description Auth
POST /v1/render Synchronous PDF/PNG generation. Returns binary document. Best for <10 pages. Responds within 30s. Bearer
POST /v1/render/async Asynchronous generation. Returns a job ID immediately. Poll status or receive webhook on completion. Best for large documents. Bearer
POST /v1/render/batch Batch generation from CSV or JSON array. Accepts up to 10,000 rows. Returns ZIP of PDFs or individual download URLs. Async by default. Bearer
GET /v1/jobs/{id} Poll the status of an async or batch job. Returns status (pending, processing, done, failed), progress percentage, and download URL when complete. Bearer
GET /v1/jobs/{id}/download Download the output file from a completed async job. Returns binary PDF or ZIP for batch jobs. Bearer
GET /v1/templates List all templates available to your account — both built-in store templates and your custom templates. Includes slug, name, category, and variable schema. Bearer
GET /v1/templates/{slug} Get metadata and variable schema for a specific template. Use this to understand what data fields the template expects. Bearer
GET /v1/templates/{slug}/preview Public endpoint. Returns a PNG preview thumbnail for a template. Cached 1 hour. No authentication required. Useful for template store UIs. None
GET /v1/usage Get current billing period usage — renders used, renders remaining, and overage count. Useful for usage monitoring in your dashboard. Bearer
DEL /v1/jobs/{id} Cancel a pending or processing async job. No-op if the job is already complete. Bearer

RESPONSES
Response format
Synchronous renders return a binary PDF or PNG. Async endpoints return JSON with job metadata.
POST /v1/render/async — Response JSON
// Async job created successfully { "job_id": "job_01J9XQZP2MNDVKR8H5CGTW4E6", "status": "pending", "template": "invoice-professional", "created_at": "2026-02-21T14:32:01Z", "webhook_url": "https://yourapp.com/webhooks/pdf" } // Poll GET /v1/jobs/{id} — job complete { "job_id": "job_01J9XQZP2MNDVKR8H5CGTW4E6", "status": "done", "render_time_ms": 387, "file_size_bytes": 48392, "download_url": "https://cdn.typsetter.dev/outputs/job_01J9.../invoice.pdf", "download_expires_at": "2026-02-22T14:32:01Z" }

RATE LIMITS & ERRORS
Rate limits and error codes
The API uses standard HTTP status codes. Rate limits are applied per API key per plan.

Rate limits by plan

PLANREQUESTS/MINCONCURRENT
Free10 req/min2
Starter60 req/min5
Pro120 req/min10
Scale300 req/min20
Business+CustomUnlimited

Rate limit headers returned on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Common error codes

CodeMeaning
200Success — PDF binary returned
202Accepted — async job created
400Bad Request — invalid JSON or missing fields
401Unauthorized — missing or invalid API key
403Forbidden — feature not available on your plan
404Template not found — check the slug
422Template render error — check variable values
429Rate limit exceeded — back off and retry
500Server error — contact support if persistent
503Service unavailable — check status.typsetter.dev

SDKs
Official SDKs and libraries
Use our typed SDKs to integrate Typsetter into your codebase in minutes. Auto-retry, response parsing, and TypeScript types included.
🟢
Node.js SDK Available
npm install @typsetter/node
🐍
Python SDK Coming Soon
pip install typsetter
🐘
PHP SDK Coming Soon
composer require typsetter/php
🦫
Go SDK Coming Soon
go get github.com/typsetter/go
Node.js SDK — quick example
import Typsetter from '@typsetter/node'; const client = new Typsetter({ apiKey: process.env.TYPSETTER_API_KEY }); // Render a PDF and save it const pdf = await client.render({ template: 'invoice-professional', data: { client_name: 'Acme Corp', total: 5170 } }); await pdf.saveTo('./invoice.pdf'); // Or get a URL const { url } = await client.renderAsync({ template: 'contract-nda', data: { party_a: 'My Company', party_b: 'Client Ltd' }, webhook: 'https://myapp.com/webhooks/pdf' });

Build your first PDF integration
in under 5 minutes.

Get your API key free. 100 PDFs per month on the free plan — no credit card required.

Get Your Free API Key → View Full Swagger Docs →
REST API · OpenAPI 3.1 · SDKs for Node.js available now