API Reference
Complete API documentation for SyntaxDoc
Complete reference for all SyntaxDoc API endpoints.
Authentication
Include your API key in the X-API-Key header:
X-API-Key: sk_live_your_api_keyAlternatively, use the Authorization header with Bearer token:
Authorization: Bearer sk_live_your_api_keyNever expose your API key in client-side code. Always make API calls from your server.
PDF Generation
POST /pdf/generate
Generate a PDF from HTML files. This is the primary endpoint for PDF generation.
Endpoint: POST https://api.syntaxdoc.com/pdf/generate
Content-Type: multipart/form-data
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
files | File[] | Yes | HTML file(s) to convert. Must include index.html or at least one .html file |
options | JSON string | No | PDF generation options (see below) |
Options Object
| Option | Type | Default | Description |
|---|---|---|---|
fileName | string | "document" | Output filename (without .pdf extension) |
format | string | "A4" | Paper format: A4, Letter, Legal, Tabloid, A3, A5 |
orientation | string | "portrait" | portrait or landscape |
width | string | - | Custom width (e.g., "6in", "15cm") - overrides format |
height | string | - | Custom height (e.g., "9in", "20cm") - overrides format |
margin | object | {top:"1cm",...} | Page margins |
margin.top | string | "1cm" | Top margin |
margin.right | string | "1cm" | Right margin |
margin.bottom | string | "1cm" | Bottom margin |
margin.left | string | "1cm" | Left margin |
preferCSSPageSize | boolean | false | Use CSS @page size instead of format |
host | boolean | false | If true, stores PDF and returns URL instead of binary |
appointmentId | string | - | Custom ID for caching (returns existing PDF if unchanged) |
regenerate | boolean | false | Force regeneration even if appointmentId exists |
userType | string | - | "guest" or "registered" for access control |
watermark | object | - | Watermark configuration (see Watermarking) |
Response
Without host: true - Returns PDF binary (application/pdf)
With host: true - Returns JSON:
{
"url": "https://api.syntaxdoc.com/api/hosted-pdfs/abc123-uuid",
"pdfId": "abc123-uuid",
"expiresAt": "2024-12-12T14:32:00.000Z"
}Example Request
const formData = new FormData();
// Add HTML file
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
h1 { color: #333; }
</style>
</head>
<body>
<h1>Invoice #1234</h1>
<p>Thank you for your purchase!</p>
</body>
</html>
`;
formData.append('files', new Blob([htmlContent], { type: 'text/html' }), 'index.html');
// Add options
formData.append('options', JSON.stringify({
fileName: 'invoice-1234',
format: 'Letter',
margin: { top: '0.5in', bottom: '0.5in', left: '0.75in', right: '0.75in' }
}));
const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
method: 'POST',
headers: {
'X-API-Key': 'sk_live_your_api_key',
},
body: formData
});
const blob = await response.blob();curl -X POST https://api.syntaxdoc.com/pdf/generate \
-H "X-API-Key: sk_live_your_api_key" \
-F "files=@invoice.html" \
-F 'options={"fileName": "invoice-1234", "format": "Letter"}' \
--output invoice.pdfimport requests
import json
files = {
'files': ('index.html', open('invoice.html', 'rb'), 'text/html')
}
data = {
'options': json.dumps({
'fileName': 'invoice-1234',
'format': 'Letter',
'margin': {'top': '0.5in', 'bottom': '0.5in'}
})
}
response = requests.post(
'https://api.syntaxdoc.com/pdf/generate',
headers={'X-API-Key': 'sk_live_your_api_key'},
files=files,
data=data
)
with open('invoice.pdf', 'wb') as f:
f.write(response.content)POST /pdf/merge
Merge multiple PDF files into a single document.
Endpoint: POST https://api.syntaxdoc.com/pdf/merge
Content-Type: multipart/form-data
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
files | File[] | Yes | PDF files to merge (in order) |
options | JSON string | No | Merge options |
Options
| Option | Type | Default | Description |
|---|---|---|---|
fileName | string | "merged-document" | Output filename |
host | boolean | false | Store PDF and return URL |
Example
const formData = new FormData();
formData.append('files', pdf1File, 'page1.pdf');
formData.append('files', pdf2File, 'page2.pdf');
formData.append('files', pdf3File, 'page3.pdf');
formData.append('options', JSON.stringify({ fileName: 'combined-document' }));
const response = await fetch('https://api.syntaxdoc.com/pdf/merge', {
method: 'POST',
headers: { 'X-API-Key': 'sk_live_your_api_key' },
body: formData
});
const mergedPdf = await response.blob();POST /pdf/generate-batch
Generate multiple PDFs from an array of HTML documents and receive them as a ZIP file.
Endpoint: POST https://api.syntaxdoc.com/pdf/generate-batch
Content-Type: application/json
Batch generation is optimized for high performance with browser reuse and parallel processing. Can generate 100+ PDFs in seconds!
Request Body
{
"documents": [
{ "fileName": "certificate-john", "htmlContent": "<html>...</html>" },
{ "fileName": "certificate-jane", "htmlContent": "<html>...</html>" }
],
"batchName": "certificates-december",
"options": {
"format": "A4",
"landscape": true
},
"stream": false,
"host": false
}| Parameter | Type | Required | Description |
|---|---|---|---|
documents | array | Yes | Array of document objects (max batch size depends on your plan) |
documents[].fileName | string | Yes | Output filename for this PDF (without .pdf extension) |
documents[].htmlContent | string | Yes | HTML content to convert |
batchName | string | No | Name for the ZIP file (default: "batch-{timestamp}") |
options | object | No | PDF options (applied to all documents) - same as /pdf/generate |
stream | boolean | No | If true, returns batchId for progress tracking |
host | boolean | No | If true, stores ZIP file and returns URL instead of binary |
Each PDF in the batch counts as 1 conversion toward your usage limit. The API validates you have enough conversions before starting.
Response Options
Standard (no stream, no host) - Returns ZIP file immediately (application/zip)
With stream: true - Returns batch ID for progress tracking:
{
"batchId": "abc123-batch-uuid",
"total": 50,
"message": "Batch processing started. Poll /pdf/progress/{batchId} for updates."
}With host: true (without stream) - Returns hosted ZIP info after completion:
{
"success": true,
"message": "Batch generation completed",
"documentsGenerated": 50,
"downloadUrl": "https://api.syntaxdoc.com/api/hosted-pdfs/zip-abc123-uuid",
"zipId": "zip-abc123-uuid",
"expiresAt": "2024-12-12T14:32:00.000Z"
}With both stream: true and host: true - Returns batch ID, then poll for hosted ZIP:
{
"batchId": "abc123-batch-uuid",
"total": 50
}GET /pdf/progress/:batchId
Poll for batch generation progress (when stream: true was used).
Endpoint: GET https://api.syntaxdoc.com/pdf/progress/:batchId
Response
{
"total": 50,
"current": 25,
"status": "processing",
"message": "Generated 25/50 PDFs"
}Status Values:
processing- Generation in progresscompleted- All PDFs generated successfullyerror- An error occurred during generationnot_found- Batch ID not found or expired
When status: "completed":
Without host: true:
{
"total": 50,
"current": 50,
"status": "completed",
"message": "Download URL: https://api.syntaxdoc.com/pdf/download/batch-abc123"
}With host: true:
{
"total": 50,
"current": 50,
"status": "completed",
"message": "{\"downloadUrl\":\"https://api.syntaxdoc.com/api/hosted-pdfs/zip-abc123\",\"zipId\":\"zip-abc123\",\"expiresAt\":\"2024-12-12T14:32:00.000Z\",\"documentsGenerated\":50}"
}GET /pdf/progress/:batchId/stream
Real-time progress updates via Server-Sent Events (SSE)
Endpoint: GET https://api.syntaxdoc.com/pdf/progress/:batchId/stream
Opens an SSE connection that pushes progress updates every 500ms.
Event Format
event: progress
data: {"total":50,"current":15,"status":"processing","message":"Generated 15/50 PDFs"}
event: progress
data: {"total":50,"current":32,"status":"processing","message":"Generated 32/50 PDFs"}
event: complete
data: {"total":50,"current":50,"status":"completed","message":"{\"downloadUrl\":\"...\"}"}Event Types:
progress- Ongoing generation updatescomplete- Batch finished (connection closes)error- Error occurred (connection closes)
Example Usage
const eventSource = new EventSource(
`https://api.syntaxdoc.com/pdf/progress/${batchId}/stream`
);
eventSource.addEventListener('progress', (event) => {
const data = JSON.parse(event.data);
console.log(`Progress: ${data.current}/${data.total} PDFs`);
// Update your UI progress bar
});
eventSource.addEventListener('complete', (event) => {
const data = JSON.parse(event.data);
const result = JSON.parse(data.message);
console.log('Download URL:', result.downloadUrl);
eventSource.close();
});
eventSource.addEventListener('error', (event) => {
console.error('Generation failed:', event.data);
eventSource.close();
});import EventSource from 'eventsource';
const eventSource = new EventSource(
`https://api.syntaxdoc.com/pdf/progress/${batchId}/stream`
);
eventSource.addEventListener('progress', (event) => {
const data = JSON.parse(event.data);
console.log(`📄 Generated ${data.current}/${data.total} PDFs`);
});
eventSource.addEventListener('complete', (event) => {
const data = JSON.parse(event.data);
const result = JSON.parse(data.message);
console.log('✅ Complete! Download:', result.downloadUrl);
eventSource.close();
});
eventSource.on('error', (error) => {
console.error('❌ Error:', error);
eventSource.close();
});Advanced Features: SyntaxDoc supports Webhooks for async batch notifications, Watermarking for document security, and QR Codes for verification and tracking.
QR Code Generation
POST /pdf/qrcode
Generate QR codes as standalone images or data URLs. Use this endpoint when you need QR codes outside of PDF generation.
For QR codes within PDFs, use the inline data-qr attribute instead - it's automatic! See QR Codes documentation.
Endpoint: POST https://api.syntaxdoc.com/pdf/qrcode
Content-Type: application/json
Request Body
{
"data": "https://syntaxdoc.com/verify/cert-12345",
"size": 300,
"margin": 2,
"errorCorrectionLevel": "H",
"darkColor": "#000000",
"lightColor": "#FFFFFF",
"format": "png"
}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
data | string | Yes | - | URL or text to encode in the QR code |
size | number | No | 200 | QR code size in pixels |
margin | number | No | 1 | White margin around QR code (0-10 modules) |
errorCorrectionLevel | string | No | "M" | Error correction: L (~7%), M (~15%), Q (~25%), H (~30%) |
darkColor | string | No | "#000000" | Dark modules color (hex format) |
lightColor | string | No | "#ffffff" | Light modules color (hex format) |
format | string | No | "png" | Output format: png (binary) or dataUrl (base64 string) |
Response
With format: "png" - Returns PNG image (image/png)
With format: "dataUrl" - Returns JSON with base64 data URL:
{
"dataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}Example Request
// Get QR code as data URL
const response = await fetch('https://api.syntaxdoc.com/pdf/qrcode', {
method: 'POST',
headers: {
'X-API-Key': 'sk_live_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: 'https://syntaxdoc.com/verify/cert-12345',
size: 300,
errorCorrectionLevel: 'H',
format: 'dataUrl'
})
});
const { dataUrl } = await response.json();
// Use dataUrl in <img src="..." /># Download as PNG
curl -X POST https://api.syntaxdoc.com/pdf/qrcode \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"data":"https://syntaxdoc.com/verify/cert-12345","size":300}' \
--output qrcode.png
# Get as data URL
curl -X POST https://api.syntaxdoc.com/pdf/qrcode \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"data":"https://syntaxdoc.com/verify/cert-12345","format":"dataUrl"}'import requests
import json
# Get as PNG buffer
response = requests.post(
'https://api.syntaxdoc.com/pdf/qrcode',
headers={'X-API-Key': 'sk_live_your_api_key'},
json={
'data': 'https://syntaxdoc.com/verify/cert-12345',
'size': 300,
'errorCorrectionLevel': 'H'
}
)
with open('qrcode.png', 'wb') as f:
f.write(response.content)
# Get as data URL
response = requests.post(
'https://api.syntaxdoc.com/pdf/qrcode',
headers={'X-API-Key': 'sk_live_your_api_key'},
json={
'data': 'https://syntaxdoc.com/verify/cert-12345',
'format': 'dataUrl'
}
)
data_url = response.json()['dataUrl']Prefer inline QR codes: For PDFs, use <img data-qr="..." /> in your HTML instead of this endpoint. It's simpler and automatic!
PDF Retrieval
GET /pdf/view/:id
View a PDF in the browser.
GET https://api.syntaxdoc.com/pdf/view/abc123-uuidReturns PDF with Content-Disposition: inline.
GET /pdf/download/:id
Download a PDF file.
GET https://api.syntaxdoc.com/pdf/download/abc123-uuidReturns PDF with Content-Disposition: attachment.
GET /pdf/metadata/:id
Get metadata for a shared PDF.
{
"userType": "guest",
"expires": "2024-12-12T14:32:00.000Z",
"fileName": "invoice",
"originalName": "invoice.pdf",
"requiresAuth": false,
"isShared": true
}Hosted PDFs
GET /api/hosted-pdfs/:pdfId
View or download a hosted PDF.
GET https://api.syntaxdoc.com/api/hosted-pdfs/abc123-uuidNo authentication required for public PDFs. Increments download counter.
GET /api/hosted-pdfs/:pdfId/metadata
Get metadata for a hosted PDF (no authentication required).
{
"id": "mongodb-id",
"pdfId": "abc123-uuid",
"originalName": "invoice.pdf",
"fileSize": 125000,
"url": "https://api.syntaxdoc.com/api/hosted-pdfs/abc123-uuid",
"expiresAt": "2024-12-12T14:32:00.000Z",
"isPublic": true,
"downloads": 15,
"createdAt": "2024-12-05T14:32:00.000Z"
}GET /api/hosted-pdfs/list
List your hosted PDFs (requires authentication via session cookie).
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Items per page |
Response:
{
"success": true,
"data": {
"pdfs": [...],
"total": 45
},
"pagination": {
"page": 1,
"limit": 20,
"total": 45,
"totalPages": 3
}
}GET /api/hosted-pdfs/stats
Get your hosted PDF statistics (requires session).
{
"success": true,
"data": {
"totalHosted": 25,
"totalDownloads": 150,
"totalSize": 52428800
}
}DELETE /api/hosted-pdfs/:pdfId
Delete a hosted PDF (requires session).
{
"success": true,
"message": "PDF deleted successfully"
}Error Response Format
All errors return JSON:
{
"statusCode": 400,
"code": "BAD_REQUEST",
"message": "No files uploaded. Please upload at least one HTML file with key \"files\"."
}| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid request parameters |
| 401 | UNAUTHORIZED | Invalid or missing API key |
| 404 | NOT_FOUND | Resource not found |
| 429 | QUOTA_EXCEEDED | API usage limit exceeded |
| 429 | HOSTED_PDF_LIMIT_REACHED | Hosted PDF storage limit reached |
| 500 | INTERNAL_SERVER_ERROR | Server error |