Getting Started
DocForge is a PDF & Document Generation API. Convert HTML, URLs, and templates into polished PDFs and images with a single API call.
Base URL
https://your-domain/api # or http://IP/api
Quick Example
Generate a PDF from raw HTML with a single cURL command:
curl -X POST https://your-domain/api/v1/pdf/from-html \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{"html": "<h1>Hello DocForge</h1><p>Your first PDF.</p>"}' \ --output document.pdf
Authentication
DocForge supports three authentication methods. Use whichever fits your workflow.
1. API Key Header (Recommended)
Pass your API key in the X-Api-Key header:
curl -H "X-Api-Key: df_live_xxxxx" https://your-domain/api/v1/pdf/from-html
2. Query Parameter
Append the key as a query parameter (useful for quick tests, not recommended for production):
https://your-domain/api/v1/pdf/from-html?api_key=df_live_xxxxx
3. JWT Bearer Token
For dashboard and account operations, use the JWT token from login:
curl -H "Authorization: Bearer <token>" https://your-domain/api/v1/templates
How to Get an API Key
- Register for a free account
- Your first API key is shown immediately after registration
- You can generate additional keys from the Dashboard → API Keys page
PDF Endpoints
Generate PDF documents from HTML markup, live URLs, or saved templates.
Generate a PDF from raw HTML content.
Request Body
| Parameter | Type | Description |
|---|---|---|
| html required | string | The HTML content to render |
| options.format | string | Paper format: A4, Letter, Legal, A3, etc. Default: A4 |
| options.landscape | boolean | Landscape orientation. Default: false |
| options.printBackground | boolean | Print background graphics. Default: true |
| options.scale | number | Scale of the webpage rendering. Default: 1 |
| options.margin | object | { top, right, bottom, left } in CSS units |
| options.displayHeaderFooter | boolean | Display header and footer. Default: false |
| options.headerTemplate | string | HTML for the header. Supports classes: date, title, url, pageNumber, totalPages |
| options.footerTemplate | string | HTML for the footer |
| options.pageRanges | string | Page ranges to print, e.g. 1-5, 8 |
| options.width | string | Paper width in CSS units (overrides format) |
| options.height | string | Paper height in CSS units (overrides format) |
| options.css | string | Additional CSS to inject before rendering |
| options.js | string | JavaScript to execute before rendering |
| options.waitForSelector | string | Wait for a CSS selector to appear before generating |
| options.waitForTimeout | number | Wait N milliseconds before generating |
Example Request
curl -X POST https://your-domain/api/v1/pdf/from-html \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{ "html": "<h1>Invoice #1042</h1><p>Total: $250.00</p>", "options": { "format": "A4", "printBackground": true, "margin": { "top": "20mm", "bottom": "20mm" } } }' \ --output invoice.pdf
const response = await fetch('https://your-domain/api/v1/pdf/from-html', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ html: '<h1>Invoice #1042</h1><p>Total: $250.00</p>', options: { format: 'A4', printBackground: true, margin: { top: '20mm', bottom: '20mm' } } }) }); const blob = await response.blob(); // Save or download the PDF blob
import requests response = requests.post( "https://your-domain/api/v1/pdf/from-html", headers={ "Content-Type": "application/json", "X-Api-Key": "df_live_xxxxx" }, json={ "html": "<h1>Invoice #1042</h1><p>Total: $250.00</p>", "options": { "format": "A4", "printBackground": True, "margin": {"top": "20mm", "bottom": "20mm"} } } ) with open("invoice.pdf", "wb") as f: f.write(response.content)
Response
Returns the PDF file as binary data with Content-Type: application/pdf.
Generate a PDF from a live URL. DocForge navigates to the page, waits for it to load, and converts it.
Request Body
| Parameter | Type | Description |
|---|---|---|
| url required | string | The URL to render as PDF |
| options | object | Same options as /pdf/from-html |
Example Request
curl -X POST https://your-domain/api/v1/pdf/from-url \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{"url": "https://example.com", "options": {"format": "A4"}}' \ --output page.pdf
const response = await fetch('https://your-domain/api/v1/pdf/from-url', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ url: 'https://example.com', options: { format: 'A4' } }) }); const blob = await response.blob();
import requests response = requests.post( "https://your-domain/api/v1/pdf/from-url", headers={"X-Api-Key": "df_live_xxxxx"}, json={"url": "https://example.com", "options": {"format": "A4"}} ) with open("page.pdf", "wb") as f: f.write(response.content)
Generate a PDF from a saved template with dynamic data. Template variables use {{variableName}} syntax.
Request Body
| Parameter | Type | Description |
|---|---|---|
| templateId required | string | ID of the saved template |
| data | object | Key-value pairs to fill template variables |
| options | object | Same options as /pdf/from-html |
Example Request
curl -X POST https://your-domain/api/v1/pdf/from-template \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{ "templateId": "tpl_invoice_v2", "data": { "customerName": "Acme Corp", "invoiceNumber": "INV-1042", "total": "$1,250.00", "items": [ {"name": "API Pro Plan", "qty": 1, "price": "$1,250.00"} ] }, "options": {"format": "A4"} }' \ --output invoice.pdf
const response = await fetch('https://your-domain/api/v1/pdf/from-template', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ templateId: 'tpl_invoice_v2', data: { customerName: 'Acme Corp', invoiceNumber: 'INV-1042', total: '$1,250.00' }, options: { format: 'A4' } }) });
import requests response = requests.post( "https://your-domain/api/v1/pdf/from-template", headers={"X-Api-Key": "df_live_xxxxx"}, json={ "templateId": "tpl_invoice_v2", "data": { "customerName": "Acme Corp", "invoiceNumber": "INV-1042", "total": "$1,250.00" }, "options": {"format": "A4"} } )
Image Endpoints
Generate screenshots and images from HTML, URLs, or templates. Supports PNG, JPEG, and WebP output formats.
Render HTML to an image. Useful for generating social cards, charts, and visual assets.
Request Body
| Parameter | Type | Description |
|---|---|---|
| html required | string | The HTML content to render |
| options.format | string | Output format: png, jpeg, or webp. Default: png |
| options.width | number | Viewport width in pixels. Default: 1280 |
| options.height | number | Viewport height in pixels. Default: 720 |
| options.scale | number | Device scale factor (1-3). Default: 1 |
| options.fullPage | boolean | Capture the full scrollable page. Default: false |
| options.quality | number | Quality 0-100 (JPEG/WebP only). Default: 80 |
| options.css | string | Additional CSS to inject |
| options.js | string | JavaScript to execute before capture |
| options.waitForSelector | string | Wait for a CSS selector to appear |
| options.waitForTimeout | number | Wait N milliseconds before capture |
Example Request
curl -X POST https://your-domain/api/v1/image/from-html \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{ "html": "<div style=\"padding:40px;background:#6366f1;color:white\"><h1>Hello</h1></div>", "options": { "format": "png", "width": 1200, "height": 630, "scale": 2 } }' \ --output social-card.png
const response = await fetch('https://your-domain/api/v1/image/from-html', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ html: '<div style="padding:40px;background:#6366f1"><h1>Hello</h1></div>', options: { format: 'png', width: 1200, height: 630, scale: 2 } }) }); const blob = await response.blob();
import requests response = requests.post( "https://your-domain/api/v1/image/from-html", headers={"X-Api-Key": "df_live_xxxxx"}, json={ "html": "<div style='padding:40px;background:#6366f1'><h1>Hello</h1></div>", "options": {"format": "png", "width": 1200, "height": 630} } ) with open("social-card.png", "wb") as f: f.write(response.content)
Response
Returns the image as binary data with the appropriate Content-Type (image/png, image/jpeg, or image/webp).
Capture a screenshot of any URL as an image.
Request Body
| Parameter | Type | Description |
|---|---|---|
| url required | string | The URL to capture |
| options | object | Same options as /image/from-html |
Example Request
curl -X POST https://your-domain/api/v1/image/from-url \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{"url": "https://example.com", "options": {"format": "png", "fullPage": true}}' \ --output screenshot.png
const response = await fetch('https://your-domain/api/v1/image/from-url', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ url: 'https://example.com', options: { format: 'png', fullPage: true } }) });
import requests response = requests.post( "https://your-domain/api/v1/image/from-url", headers={"X-Api-Key": "df_live_xxxxx"}, json={"url": "https://example.com", "options": {"format": "png", "fullPage": True}} )
Render a saved template as an image with dynamic data.
Request Body
| Parameter | Type | Description |
|---|---|---|
| templateId required | string | ID of the saved template |
| data | object | Key-value pairs for template variables |
| options | object | Same options as /image/from-html |
Example Request
curl -X POST https://your-domain/api/v1/image/from-template \ -H "Content-Type: application/json" \ -H "X-Api-Key: df_live_xxxxx" \ -d '{ "templateId": "tpl_og_card", "data": {"title": "My Blog Post", "author": "John"}, "options": {"format": "png", "width": 1200, "height": 630} }' \ --output og-card.png
const response = await fetch('https://your-domain/api/v1/image/from-template', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'df_live_xxxxx' }, body: JSON.stringify({ templateId: 'tpl_og_card', data: { title: 'My Blog Post', author: 'John' }, options: { format: 'png', width: 1200, height: 630 } }) });
import requests response = requests.post( "https://your-domain/api/v1/image/from-template", headers={"X-Api-Key": "df_live_xxxxx"}, json={ "templateId": "tpl_og_card", "data": {"title": "My Blog Post", "author": "John"}, "options": {"format": "png", "width": 1200, "height": 630} } )
Templates
Save reusable HTML templates with {{variableName}} placeholders. Fill them with dynamic data when generating PDFs or images.
{{customerName}}, {{total}}, {{items}}. Variables are replaced at render time with values from the data object.
List all templates for the authenticated user.
Example Response
{
"success": true,
"data": [
{
"id": "tpl_invoice_v2",
"name": "Invoice Template",
"variables": ["customerName", "invoiceNumber", "total"],
"createdAt": "2026-03-15T10:30:00Z",
"updatedAt": "2026-03-20T14:22:00Z"
}
]
}
Get a single template by ID, including its full HTML content.
Example Response
{
"success": true,
"data": {
"id": "tpl_invoice_v2",
"name": "Invoice Template",
"html": "<h1>Invoice {{invoiceNumber}}</h1><p>To: {{customerName}}</p>",
"variables": ["customerName", "invoiceNumber", "total"],
"createdAt": "2026-03-15T10:30:00Z",
"updatedAt": "2026-03-20T14:22:00Z"
}
}
Create a new template. Requires JWT authentication.
Request Body
| Parameter | Type | Description |
|---|---|---|
| name required | string | Template display name |
| html required | string | HTML content with {{variable}} placeholders |
Example Request
curl -X POST https://your-domain/api/v1/templates \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <jwt_token>" \ -d '{ "name": "Invoice Template", "html": "<h1>Invoice {{invoiceNumber}}</h1><p>To: {{customerName}}</p><p>Total: {{total}}</p>" }'
Update an existing template's name or HTML content.
Request Body
| Parameter | Type | Description |
|---|---|---|
| name | string | Updated template name |
| html | string | Updated HTML content |
Example Request
curl -X PUT https://your-domain/api/v1/templates/tpl_invoice_v2 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <jwt_token>" \ -d '{"name": "Invoice Template v3", "html": "<h1>Updated Invoice</h1>"}'
Permanently delete a template.
Example Request
curl -X DELETE https://your-domain/api/v1/templates/tpl_invoice_v2 \ -H "Authorization: Bearer <jwt_token>"
Example Response
{
"success": true,
"message": "Template deleted successfully"
}
Error Handling
All errors follow a consistent JSON format. The HTTP status code and error body both indicate the problem.
Error Response Format
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable description of what went wrong"
}
}
Error Codes
| Code | HTTP Status | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key / JWT token |
| FORBIDDEN | 403 | Valid credentials but insufficient permissions |
| NOT_FOUND | 404 | Requested resource (template, etc.) not found |
| BAD_REQUEST | 400 | Malformed request body or missing required fields |
| VALIDATION_ERROR | 422 | Input validation failed (invalid URL, bad options, etc.) |
| RATE_LIMIT_EXCEEDED | 429 | Too many requests per minute |
| QUOTA_EXCEEDED | 429 | Monthly render quota has been exceeded |
| RENDER_FAILED | 500 | The rendering engine failed to produce output |
| INTERNAL_ERROR | 500 | An unexpected server error occurred |
RATE_LIMIT_EXCEEDED error, the response includes a Retry-After header indicating how many seconds to wait before retrying.
Rate Limits
API requests are rate-limited per API key. Monthly quotas depend on your plan.
Per-Minute Limit
All plans share the same per-minute rate limit: 100 requests per minute per API key.
Monthly Quotas
| Plan | Monthly Renders | Quota |
|---|---|---|
| Free | For testing and small projects | 100 |
| Starter | For growing applications | 2,000 |
| Pro | For production workloads | 10,000 |
| Business | For high-volume usage | 50,000 |
Response Headers
Every API response includes quota and performance headers:
| Header | Type | Description |
|---|---|---|
| X-Quota-Remaining | number | Renders remaining in the current billing period |
| X-Quota-Limit | number | Total renders allowed per billing period |
| X-Render-Time-Ms | number | Time taken to render the document in milliseconds |
SDKs
Official client libraries are in development. In the meantime, the REST API works with any HTTP client in any language.