Developer API
PDF Generator provides a REST API for programmatic access. Generate PDFs, manage templates and variables, and download documents — all from your own applications.
Authentication
All API requests require an API key. Generate your key from Profile → API Keys in the web app.
Include the key in the Api-Key header:
Api-Key: pk_your_api_key_here
The same endpoints also support JWT authentication via the Auth-Token header (used by the web app). API keys are for external integrations.
Learn more about API key management →
Base URL
https://app.generator.rest/api
API Reference
Full OpenAPI documentation with all endpoints, request/response schemas, and parameters:
Endpoint Summary
Templates
| Method | Endpoint | Description |
|---|---|---|
GET | /pdf-template | List templates |
GET | /pdf-template/{id} | Get a template |
POST | /pdf-template | Create a template |
PATCH | /pdf-template/{id} | Update a template |
PUT | /pdf-template/{id} | Replace a template |
DELETE | /pdf-template/{id} | Delete a template |
GET | /pdf-template/{id}/files | List template files |
POST | /pdf-template/{id}/files | Upload template files |
GET | /pdf-template/{id}/files/content/{file} | Download file content |
DELETE | /pdf-template/{id}/files/{file} | Delete a file |
POST | /pdf-template/{id}/files/from-zip | Upload files from ZIP |
POST | /pdf-template/render | Render a PDF |
Variables
| Method | Endpoint | Description |
|---|---|---|
GET | /template-variables | List variables |
GET | /template-variables/{id} | Get a variable |
POST | /template-variables | Create a variable |
PATCH | /template-variables/{id} | Update a variable |
PUT | /template-variables/{id} | Replace a variable |
DELETE | /template-variables/{id} | Delete a variable |
Documents
| Method | Endpoint | Description |
|---|---|---|
GET | /documents | List generated documents |
GET | /documents/{key} | Download a document |
Code Examples
cURL
List Templates
curl -H "Api-Key: pk_your_api_key_here" \
https://app.generator.rest/api/pdf-template
Create a Template
curl -X POST \
-H "Api-Key: pk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Invoice",
"type": "full",
"renderer": "itext",
"pageSize": "A4",
"margin": { "top": 36, "right": 36, "bottom": 36, "left": 36 }
}' \
https://app.generator.rest/api/pdf-template
Upload a File to a Template
curl -X POST \
-H "Api-Key: pk_your_api_key_here" \
-F "index.html=@/path/to/index.html" \
-F "header.html=@/path/to/header.html" \
https://app.generator.rest/api/pdf-template/123/files
Render a PDF
curl -X POST \
-H "Api-Key: pk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"fileName": "invoice-0042.pdf",
"context": {
"customerName": "Acme Corp",
"invoiceDate": "2026-06-14",
"totalAmount": "1250.00"
},
"metadata": {
"info": {
"title": "Invoice for Acme Corp",
"author": "Billing Department",
"subject": "Monthly Invoice"
}
}
}' \
https://app.generator.rest/api/pdf-template/render
List Documents
curl -H "Api-Key: pk_your_api_key_here" \
"https://app.generator.rest/api/documents?limit=10&nameFilter=invoice"
Download a Document
curl -H "Api-Key: pk_your_api_key_here" \
-o invoice-0042.pdf \
https://app.generator.rest/api/documents/invoice-0042.pdf
JavaScript (fetch)
const API_BASE = "https://app.generator.rest/api";
const API_KEY = "pk_your_api_key_here";
// List templates
async function listTemplates() {
const res = await fetch(`${API_BASE}/pdf-template`, {
headers: { "Api-Key": API_KEY },
});
const data = await res.json();
return data.results;
}
// Create a template
async function createTemplate() {
const res = await fetch(`${API_BASE}/pdf-template`, {
method: "POST",
headers: {
"Api-Key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Report",
type: "full",
renderer: "itext",
pageSize: "A4",
margin: { top: 36, right: 36, bottom: 36, left: 36 },
}),
});
return res.json();
}
// Upload files to a template
async function uploadFiles(templateId, files) {
const formData = new FormData();
for (const [name, content] of Object.entries(files)) {
formData.append(name, new Blob([content]), name);
}
const res = await fetch(
`${API_BASE}/pdf-template/${templateId}/files`,
{
method: "POST",
headers: { "Api-Key": API_KEY },
body: formData,
},
);
return res.json();
}
// Render a PDF
async function renderPdf(templateId, context) {
const res = await fetch(`${API_BASE}/pdf-template/render`, {
method: "POST",
headers: {
"Api-Key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
templateId,
context,
metadata: {
info: {
title: "Generated Document",
author: "API Integration",
},
},
}),
});
const { eTag, fileName } = await res.json();
return fileName;
}
// Download a document
async function downloadDocument(fileName) {
const res = await fetch(
`${API_BASE}/documents/${encodeURIComponent(fileName)}`,
{ headers: { "Api-Key": API_KEY } },
);
const blob = await res.blob();
return blob;
}
// Full workflow: generate and download
async function generateAndDownload(templateId, variables) {
const fileName = await renderPdf(templateId, variables);
const pdfBlob = await downloadDocument(fileName);
// Save or process the blob
const url = URL.createObjectURL(pdfBlob);
window.open(url);
}
Python (requests)
import requests
API_BASE = "https://app.generator.rest/api"
API_KEY = "pk_your_api_key_here"
HEADERS = {"Api-Key": API_KEY}
# List templates
def list_templates():
res = requests.get(f"{API_BASE}/pdf-template", headers=HEADERS)
res.raise_for_status()
return res.json()["results"]
# Create a template
def create_template(name, page_size="A4", renderer="itext"):
res = requests.post(
f"{API_BASE}/pdf-template",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"name": name,
"type": "full",
"renderer": renderer,
"pageSize": page_size,
"margin": {"top": 36, "right": 36, "bottom": 36, "left": 36},
},
)
res.raise_for_status()
return res.json()
# Upload files to a template
def upload_files(template_id, files_dict):
# files_dict: {"index.html": "<html>...</html>", "header.html": "..."}
res = requests.post(
f"{API_BASE}/pdf-template/{template_id}/files",
headers=HEADERS,
files={name: (name, content) for name, content in files_dict.items()},
)
res.raise_for_status()
return res.json()
# Render a PDF
def render_pdf(template_id, context, metadata=None):
payload = {
"templateId": template_id,
"context": context,
}
if metadata:
payload["metadata"] = metadata
res = requests.post(
f"{API_BASE}/pdf-template/render",
headers={**HEADERS, "Content-Type": "application/json"},
json=payload,
)
res.raise_for_status()
return res.json()["fileName"]
# Download a document
def download_document(file_name, output_path):
res = requests.get(
f"{API_BASE}/documents/{file_name}",
headers=HEADERS,
stream=True,
)
res.raise_for_status()
with open(output_path, "wb") as f:
for chunk in res.iter_content(chunk_size=8192):
f.write(chunk)
# Full workflow
def generate_invoice():
context = {
"customerName": "Acme Corp",
"invoiceDate": "2026-06-14",
"totalAmount": 1250.00,
"lineItems": [
{"description": "Widget A", "quantity": 2, "price": 500.00},
{"description": "Widget B", "quantity": 1, "price": 250.00},
],
}
metadata = {
"info": {
"title": f"Invoice for {context['customerName']}",
"author": "Billing System",
"subject": "Monthly Invoice",
"keywords": "invoice, billing",
}
}
file_name = render_pdf(123, context, metadata)
download_document(file_name, f"./output/{file_name}")
print(f"Downloaded: {file_name}")
Pagination
List endpoints support pagination:
| Parameter | Description |
|---|---|
limit | Number of results per page |
offset | Zero-based offset for page |
start | Pagination offset (alternative) |
Response includes total count and results array.
Filtering & Sorting
List endpoints support query filters:
GET /pdf-template?filter[]=name||$cont||invoice&order[]=createdAt,DESC
Common filter operators: $eq, $cont (contains), $gt, $lt, $between.
Error Handling
The API returns standard HTTP status codes:
| Status | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad request — check your request body |
| 401 | Unauthorized — invalid or missing API key |
| 404 | Not found — template, variable, or document doesn't exist |
| 422 | Validation error — check required fields |
| 500 | Server error |
Error responses include:
{
"statusCode": 422,
"message": "Validation failed",
"error": "Unprocessable Entity"
}
Rate Limits
Rate limits vary by subscription tier. Exceeding limits returns a 429 Too Many Requests response. Upgrade your plan for higher limits.