SyntaxdocSyntaxdoc

Examples

Real-world examples of HTML to PDF conversion with SyntaxDoc API

Real-world examples to help you get started with common use cases. All examples use the actual SyntaxDoc API endpoints.


Invoice Generation

Generate professional invoices from HTML templates.

// Create HTML file content
const invoiceHtml = `
<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: 'Helvetica', sans-serif; padding: 40px; color: #333; }
    .header { display: flex; justify-content: space-between; margin-bottom: 40px; }
    .logo { font-size: 24px; font-weight: bold; }
    .invoice-info { text-align: right; }
    .invoice-number { font-size: 20px; color: #666; }
    table { width: 100%; border-collapse: collapse; margin: 30px 0; }
    th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
    th { background: #f8f9fa; font-weight: 600; }
    .total-row { font-weight: bold; font-size: 18px; }
    .total-row td { border-top: 2px solid #333; }
  </style>
</head>
<body>
  <div class="header">
    <div class="logo">ACME Inc.</div>
    <div class="invoice-info">
      <div class="invoice-number">Invoice #INV-2024-001</div>
      <div>Date: January 15, 2024</div>
    </div>
  </div>
  
  <table>
    <thead>
      <tr>
        <th>Description</th>
        <th>Quantity</th>
        <th>Unit Price</th>
        <th>Total</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Web Development Services</td>
        <td>40 hrs</td>
        <td>$150.00</td>
        <td>$6,000.00</td>
      </tr>
      <tr>
        <td>UI/UX Design</td>
        <td>20 hrs</td>
        <td>$125.00</td>
        <td>$2,500.00</td>
      </tr>
      <tr class="total-row">
        <td colspan="3">Total</td>
        <td>$8,500.00</td>
      </tr>
    </tbody>
  </table>
</body>
</html>
`;

// Create FormData
const formData = new FormData();
const htmlBlob = new Blob([invoiceHtml], { type: 'text/html' });
formData.append('files', htmlBlob, 'index.html');
formData.append('options', JSON.stringify({
  fileName: 'invoice-2024-001',
  format: 'Letter',
  margin: { top: '0.5in', bottom: '0.5in', left: '0.5in', right: '0.5in' }
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: {
    'X-API-Key': 'YOUR_API_KEY',
  },
  body: formData
});

const pdfBuffer = await response.arrayBuffer();
// Save or send the PDF
import requests
import json

# Create HTML content
invoice_html = '''
<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: 'Helvetica', sans-serif; padding: 40px; color: #333; }
    .header { display: flex; justify-content: space-between; margin-bottom: 40px; }
    .logo { font-size: 24px; font-weight: bold; }
    table { width: 100%; border-collapse: collapse; margin: 30px 0; }
    th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
    th { background: #f8f9fa; font-weight: 600; }
    .total-row { font-weight: bold; font-size: 18px; }
  </style>
</head>
<body>
  <div class="header">
    <div class="logo">ACME Inc.</div>
    <div>Invoice #INV-2024-001</div>
  </div>
  <!-- Table content here -->
</body>
</html>
'''

# Prepare files and options
files = [
    ('files', ('index.html', invoice_html, 'text/html')),
]

options = {
    'fileName': 'invoice-2024-001',
    'format': 'Letter',
    'margin': {'top': '0.5in', 'bottom': '0.5in', 'left': '0.5in', 'right': '0.5in'}
}

response = requests.post(
    'https://api.syntaxdoc.com/pdf/generate',
    headers={'X-API-Key': 'YOUR_API_KEY'},
    files=files,
    data={'options': json.dumps(options)}
)

with open('invoice.pdf', 'wb') as f:
    f.write(response.content)
# Save your HTML to a file first (invoice.html)
curl -X POST https://api.syntaxdoc.com/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "files=@invoice.html" \
  -F 'options={"fileName":"invoice-2024-001","format":"Letter","margin":{"top":"0.5in","bottom":"0.5in"}}' \
  -o invoice.pdf

Report with Charts (SVG)

Include charts using inline SVGs for perfect quality at any scale.

const reportHtml = `
<!DOCTYPE html>
<html>
<head>
  <style>
    body { font-family: system-ui, sans-serif; padding: 40px; }
    h1 { color: #1a1a1a; margin-bottom: 20px; }
    .metrics { display: flex; gap: 20px; margin: 30px 0; }
    .metric { 
      padding: 20px; 
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
      border-radius: 12px; 
      color: white;
      flex: 1;
    }
    .metric-value { font-size: 32px; font-weight: bold; }
    .metric-label { opacity: 0.9; margin-top: 5px; }
    .chart-container { margin: 30px 0; background: #f8f9fa; padding: 20px; border-radius: 12px; }
  </style>
</head>
<body>
  <h1>📊 Monthly Performance Report</h1>
  <p style="color: #666;">January 2024</p>
  
  <div class="metrics">
    <div class="metric">
      <div class="metric-value">$124,500</div>
      <div class="metric-label">Revenue</div>
    </div>
    <div class="metric">
      <div class="metric-value">1,234</div>
      <div class="metric-label">New Users</div>
    </div>
    <div class="metric">
      <div class="metric-value">98.5%</div>
      <div class="metric-label">Uptime</div>
    </div>
  </div>
  
  <div class="chart-container">
    <h3 style="margin-bottom: 15px;">Monthly Growth</h3>
    <svg width="100%" height="200" viewBox="0 0 400 200" preserveAspectRatio="xMidYMid meet">
      <rect x="20" y="150" width="40" height="30" fill="#667eea" rx="4"/>
      <rect x="80" y="120" width="40" height="60" fill="#667eea" rx="4"/>
      <rect x="140" y="80" width="40" height="100" fill="#667eea" rx="4"/>
      <rect x="200" y="60" width="40" height="120" fill="#667eea" rx="4"/>
      <rect x="260" y="40" width="40" height="140" fill="#667eea" rx="4"/>
      <rect x="320" y="20" width="40" height="160" fill="#764ba2" rx="4"/>
      <!-- Labels -->
      <text x="40" y="195" font-size="12" text-anchor="middle">Jul</text>
      <text x="100" y="195" font-size="12" text-anchor="middle">Aug</text>
      <text x="160" y="195" font-size="12" text-anchor="middle">Sep</text>
      <text x="220" y="195" font-size="12" text-anchor="middle">Oct</text>
      <text x="280" y="195" font-size="12" text-anchor="middle">Nov</text>
      <text x="340" y="195" font-size="12" text-anchor="middle">Dec</text>
    </svg>
  </div>
</body>
</html>
`;

const formData = new FormData();
const htmlBlob = new Blob([reportHtml], { type: 'text/html' });
formData.append('files', htmlBlob, 'index.html');
formData.append('options', JSON.stringify({
  fileName: 'monthly-report',
  format: 'A4'
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const pdf = await response.blob();
curl -X POST https://api.syntaxdoc.com/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "files=@report.html" \
  -F 'options={"fileName":"monthly-report","format":"A4"}' \
  -o monthly-report.pdf

Tip: SVG graphics are rendered perfectly at any scale. For charts, consider using libraries like Chart.js or D3.js to generate SVG, then include it in your HTML.


Host PDF with Shareable URL

Generate a PDF and store it on the server for sharing.

const formData = new FormData();
formData.append('files', htmlFile);
formData.append('options', JSON.stringify({
  fileName: 'shareable-document',
  format: 'A4',
  host: true  // Store on server
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const data = await response.json();
console.log('PDF URL:', data.url);           // Shareable URL
console.log('PDF ID:', data.pdfId);          // For management
console.log('Expires:', data.expiresAt);     // Expiration date

// Share the URL with anyone!
// They can access it without authentication
import requests
import json

files = [('files', ('index.html', open('document.html', 'rb'), 'text/html'))]

options = {
    'fileName': 'shareable-document',
    'format': 'A4',
    'host': True  # Store on server
}

response = requests.post(
    'https://api.syntaxdoc.com/pdf/generate',
    headers={'X-API-Key': 'YOUR_API_KEY'},
    files=files,
    data={'options': json.dumps(options)}
)

data = response.json()
print(f"PDF URL: {data['url']}")
print(f"PDF ID: {data['pdfId']}")
print(f"Expires: {data['expiresAt']}")
curl -X POST https://api.syntaxdoc.com/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "files=@document.html" \
  -F 'options={"fileName":"shareable-document","format":"A4","host":true}'

# Response:
# {
#   "url": "https://api.syntaxdoc.com/pdf/hosted/abc123.pdf",
#   "pdfId": "abc123",
#   "expiresAt": "2024-01-15T00:00:00.000Z"
# }

Merge Multiple PDFs

Combine multiple PDF documents into one.

const formData = new FormData();

// Add multiple PDF files
formData.append('files', pdfFile1, 'cover.pdf');
formData.append('files', pdfFile2, 'content.pdf');
formData.append('files', pdfFile3, 'appendix.pdf');

formData.append('options', JSON.stringify({
  fileName: 'complete-document',
  host: true  // Optional: host the merged PDF
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/merge', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

if (response.headers.get('content-type')?.includes('application/json')) {
  const data = await response.json();
  console.log('Merged PDF URL:', data.url);
} else {
  const mergedPdf = await response.blob();
  // Download the merged PDF
}
import requests
import json

files = [
    ('files', ('cover.pdf', open('cover.pdf', 'rb'), 'application/pdf')),
    ('files', ('content.pdf', open('content.pdf', 'rb'), 'application/pdf')),
    ('files', ('appendix.pdf', open('appendix.pdf', 'rb'), 'application/pdf')),
]

options = {
    'fileName': 'complete-document',
    'host': True
}

response = requests.post(
    'https://api.syntaxdoc.com/pdf/merge',
    headers={'X-API-Key': 'YOUR_API_KEY'},
    files=files,
    data={'options': json.dumps(options)}
)

data = response.json()
print(f"Merged PDF URL: {data['url']}")
curl -X POST https://api.syntaxdoc.com/pdf/merge \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "files=@cover.pdf" \
  -F "files=@content.pdf" \
  -F "files=@appendix.pdf" \
  -F 'options={"fileName":"complete-document"}' \
  -o merged.pdf

PDFs are merged in the order they are uploaded. Make sure to add files in the desired sequence.


Batch Convert Multiple HTML Files

Convert multiple HTML files in a single request.

const formData = new FormData();

// Add multiple HTML files
formData.append('files', reportHtml, 'report.html');
formData.append('files', invoiceHtml, 'invoice.html');
formData.append('files', receiptHtml, 'receipt.html');

formData.append('options', JSON.stringify({
  outputType: 'zip',      // Get all PDFs in a ZIP
  fileName: 'batch-results'
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate-batch', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const data = await response.json();

// Track progress
const checkProgress = async () => {
  const progress = await fetch(
    `https://api.syntaxdoc.com/pdf/progress/${data.batchId}`,
    { headers: { 'X-API-Key': 'YOUR_API_KEY' } }
  );
  const status = await progress.json();
  console.log(`Progress: ${status.current}/${status.total}`);
  
  if (status.status === 'completed') {
    // Download the ZIP
    window.location.href = 
      `https://api.syntaxdoc.com/pdf/download-zip/${data.fileId}`;
  } else if (status.status !== 'error') {
    setTimeout(checkProgress, 1000);
  }
};

checkProgress();
# Upload batch
curl -X POST https://api.syntaxdoc.com/pdf/generate-batch \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "files=@report.html" \
  -F "files=@invoice.html" \
  -F "files=@receipt.html" \
  -F 'options={"outputType":"zip","fileName":"batch-results"}'

# Response includes batchId and fileId
# Check progress:
curl https://api.syntaxdoc.com/pdf/progress/BATCH_ID

# Download when complete:
curl https://api.syntaxdoc.com/pdf/download-zip/FILE_ID -o batch-results.zip

HTML with External Resources

Include CSS, images, and fonts with your HTML.

const formData = new FormData();

// HTML file (must be named index.html or any .html file)
formData.append('files', htmlFile, 'index.html');

// CSS file - reference it in your HTML as <link href="styles.css">
formData.append('files', cssFile, 'styles.css');

// Image files - reference as <img src="logo.png">
formData.append('files', logoImage, 'logo.png');
formData.append('files', headerImage, 'images/header.jpg');

// Font files - reference in CSS @font-face
formData.append('files', customFont, 'fonts/MyFont.woff2');

formData.append('options', JSON.stringify({
  fileName: 'styled-document',
  format: 'A4'
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

Example HTML structure:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="styles.css">
  <style>
    @font-face {
      font-family: 'MyFont';
      src: url('fonts/MyFont.woff2') format('woff2');
    }
  </style>
</head>
<body>
  <img src="logo.png" alt="Logo">
  <img src="images/header.jpg" alt="Header">
  <h1>My Document</h1>
</body>
</html>

Important: All resource paths in your HTML must be relative (not absolute URLs). The API will resolve them from the uploaded files.


Using Google Fonts

Include web fonts in your documents.

<!DOCTYPE html>
<html>
<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
  <style>
    body { font-family: 'Inter', sans-serif; }
    h1 { font-weight: 700; }
    p { font-weight: 400; }
  </style>
</head>
<body>
  <h1>Custom Font Example</h1>
  <p>This text uses the Inter font from Google Fonts.</p>
</body>
</html>

Google Fonts and other web fonts are automatically fetched and cached by the API. No additional configuration needed.


Certificate Generation

Create landscape certificates with custom dimensions.

const certificateHtml = `
<!DOCTYPE html>
<html>
<head>
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Open+Sans&display=swap" rel="stylesheet">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Open Sans', sans-serif;
      background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .certificate {
      background: white;
      border: 3px solid #d4af37;
      padding: 60px;
      text-align: center;
      box-shadow: 0 20px 60px rgba(0,0,0,0.1);
    }
    .title {
      font-family: 'Playfair Display', serif;
      font-size: 48px;
      color: #2c3e50;
      margin-bottom: 20px;
    }
    .subtitle { color: #666; font-size: 14px; letter-spacing: 3px; }
    .recipient {
      font-family: 'Playfair Display', serif;
      font-size: 36px;
      color: #d4af37;
      margin: 30px 0;
      border-bottom: 2px solid #d4af37;
      padding-bottom: 10px;
    }
    .description { color: #666; line-height: 1.8; margin: 20px 0; }
    .date { margin-top: 40px; color: #666; }
  </style>
</head>
<body>
  <div class="certificate">
    <div class="subtitle">CERTIFICATE OF COMPLETION</div>
    <div class="title">Excellence Award</div>
    <p class="description">This is to certify that</p>
    <div class="recipient">John Doe</div>
    <p class="description">
      has successfully completed the Advanced Web Development course<br>
      with outstanding performance and dedication.
    </p>
    <div class="date">Awarded on January 15, 2024</div>
  </div>
</body>
</html>
`;

const formData = new FormData();
formData.append('files', new Blob([certificateHtml], { type: 'text/html' }), 'index.html');
formData.append('options', JSON.stringify({
  fileName: 'certificate-john-doe',
  format: 'Letter',
  orientation: 'landscape',
  margin: { top: '0', right: '0', bottom: '0', left: '0' },
  host: true
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const data = await response.json();
// data.url contains the shareable certificate URL

Certificate with QR Code Verification

Add QR codes to certificates for instant verification - no separate API call needed!

const certificateHtml = `
<!DOCTYPE html>
<html>
<head>
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Open+Sans&display=swap" rel="stylesheet">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Open Sans', sans-serif;
      background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
      padding: 40px;
    }
    .certificate {
      background: white;
      border: 3px solid #d4af37;
      padding: 60px;
      text-align: center;
      box-shadow: 0 20px 60px rgba(0,0,0,0.1);
    }
    .title {
      font-family: 'Playfair Display', serif;
      font-size: 48px;
      color: #2c3e50;
      margin-bottom: 20px;
    }
    .recipient {
      font-family: 'Playfair Display', serif;
      font-size: 36px;
      color: #d4af37;
      margin: 30px 0;
      border-bottom: 2px solid #d4af37;
      padding-bottom: 10px;
    }
    .qr-section {
      margin-top: 40px;
      padding-top: 30px;
      border-top: 2px solid #eee;
    }
    .qr-label {
      font-size: 12px;
      color: #666;
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <div class="certificate">
    <div class="title">Certificate of Achievement</div>
    <p>This is to certify that</p>
    <div class="recipient">Jane Smith</div>
    <p>has successfully completed the Advanced Web Development course<br>
    with outstanding performance and dedication.</p>
    
    <div class="qr-section">
      <p class="qr-label">Scan to verify authenticity:</p>
      <img data-qr="https://yourapp.com/verify/cert-2024-12345" 
           data-qr-size="150" 
           data-qr-error-correction="H"
           alt="Verification QR Code" />
      <p class="qr-label" style="margin-top: 10px;">Certificate ID: CERT-2024-12345</p>
    </div>
  </div>
</body>
</html>
`;

const formData = new FormData();
formData.append('files', new Blob([certificateHtml], { type: 'text/html' }), 'index.html');
formData.append('options', JSON.stringify({
  fileName: 'certificate-jane-smith',
  format: 'Letter',
  orientation: 'landscape'
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const pdfBlob = await response.blob();
// QR code is automatically generated and embedded!

The QR code is automatically generated during PDF creation - no separate API calls needed! Perfect for certificates, tickets, and invoices.

Learn more about QR codes →


Confidential Document with Watermark

Add watermarks for branding, security, or document status indication.

const confidentialHtml = `
<!DOCTYPE html>
<html>
<head>
  <style>
    body { font-family: Arial, sans-serif; padding: 40px; }
    .header { border-bottom: 2px solid #333; padding-bottom: 20px; margin-bottom: 30px; }
    h1 { color: #333; }
    .section { margin: 30px 0; }
    .section h2 { color: #666; font-size: 18px; }
    p { line-height: 1.6; color: #444; }
  </style>
</head>
<body>
  <div class="header">
    <h1>Confidential Report</h1>
    <p>Q4 2024 Financial Summary</p>
  </div>
  
  <div class="section">
    <h2>Executive Summary</h2>
    <p>This document contains sensitive financial information that is intended
    for internal use only. Revenue increased by 23% year-over-year...</p>
  </div>
  
  <div class="section">
    <h2>Detailed Analysis</h2>
    <p>The following sections contain proprietary data and strategic insights...</p>
  </div>
</body>
</html>
`;

const formData = new FormData();
formData.append('files', new Blob([confidentialHtml], { type: 'text/html' }), 'index.html');
formData.append('options', JSON.stringify({
  fileName: 'confidential-q4-report',
  format: 'A4',
  watermark: {
    text: 'CONFIDENTIAL',
    fontSize: 60,
    opacity: 0.2,
    rotation: -45,
    color: { r: 1, g: 0, b: 0 },  // Red watermark
    position: 'diagonal'
  }
}));

const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
});

const pdfBlob = await response.blob();
// Watermark is applied to every page!

Watermarks are automatically applied to all pages in the PDF. Perfect for drafts, confidential documents, or branding.

Learn more about watermarks →


Batch Generation with Real-Time Progress

Generate hundreds of PDFs with real-time streaming updates. Perfect for certificates, invoices, or reports at scale.

Blazing Fast Performance - Generate 100+ PDFs in seconds with browser reuse and parallel processing!

// Generate 100 certificates with real-time progress via SSE
async function generateBatchWithStreaming() {
  // Start batch generation
  const startResponse = await fetch('https://api.syntaxdoc.com/pdf/generate-batch', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      documents: Array.from({ length: 100 }, (_, i) => ({
        fileName: `certificate-${i + 1}`,
        htmlContent: `
          <html>
            <body style="font-family: Arial; padding: 60px; text-align: center;">
              <h1 style="color: #d4af37;">Certificate of Achievement</h1>
              <h2>Awarded to: Student ${i + 1}</h2>
              <p>For outstanding performance in Web Development</p>
            </body>
          </html>
        `
      })),
      batchName: 'certificates-2024',
      options: { format: 'Letter', orientation: 'landscape' },
      stream: true,
      host: true  // Store ZIP file for later download
    })
  });

  const { batchId, total } = await startResponse.json();
  console.log(`Started batch: ${batchId} (${total} PDFs)`);

  // Connect to SSE stream for real-time updates
  const eventSource = new EventSource(
    `https://api.syntaxdoc.com/pdf/progress/${batchId}/stream`
  );

  eventSource.addEventListener('progress', (event) => {
    const data = JSON.parse(event.data);
    const percentage = Math.round((data.current / data.total) * 100);
    console.log(`📄 Progress: ${percentage}% (${data.current}/${data.total})`);
    
    // Update your progress bar
    document.getElementById('progress-bar').style.width = `${percentage}%`;
    document.getElementById('progress-text').textContent = 
      `Generated ${data.current} of ${data.total} PDFs`;
  });

  eventSource.addEventListener('complete', (event) => {
    const data = JSON.parse(event.data);
    const result = JSON.parse(data.message);
    
    console.log('✅ Batch complete!');
    console.log('Download URL:', result.downloadUrl);
    console.log('ZIP ID:', result.zipId);
    console.log('Expires:', result.expiresAt);
    
    // Provide download link to user
    window.location.href = result.downloadUrl;
    
    eventSource.close();
  });

  eventSource.addEventListener('error', () => {
    console.error('❌ Stream error');
    eventSource.close();
  });
}

generateBatchWithStreaming();
// Generate batch with polling (no SSE support)
async function generateBatchWithPolling() {
  // Start batch
  const startResponse = await fetch('https://api.syntaxdoc.com/pdf/generate-batch', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      documents: [
        { fileName: 'invoice-001', htmlContent: '<html>...</html>' },
        { fileName: 'invoice-002', htmlContent: '<html>...</html>' },
        // ... more documents
      ],
      stream: true,
      host: true
    })
  });

  const { batchId, total } = await startResponse.json();

  // Poll for progress every 2 seconds
  const pollInterval = setInterval(async () => {
    const progressResponse = await fetch(
      `https://api.syntaxdoc.com/pdf/progress/${batchId}`
    );
    const progress = await progressResponse.json();

    console.log(`Progress: ${progress.current}/${progress.total}`);

    if (progress.status === 'completed') {
      clearInterval(pollInterval);
      const result = JSON.parse(progress.message);
      console.log('Download:', result.downloadUrl);
      window.location.href = result.downloadUrl;
    } else if (progress.status === 'error') {
      clearInterval(pollInterval);
      console.error('Batch failed:', progress.message);
    }
  }, 2000);
}
import requests
import json
import time

# Generate batch
response = requests.post(
    'https://api.syntaxdoc.com/pdf/generate-batch',
    headers={
        'X-API-Key': 'YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'documents': [
            {
                'fileName': f'report-{i}',
                'htmlContent': f'<html><body><h1>Report {i}</h1></body></html>'
            }
            for i in range(1, 51)  # Generate 50 PDFs
        ],
        'batchName': 'monthly-reports',
        'stream': True,
        'host': True
    }
)

data = response.json()
batch_id = data['batchId']
total = data['total']
print(f"Started batch: {batch_id} ({total} PDFs)")

# Poll for progress
while True:
    progress_response = requests.get(
        f'https://api.syntaxdoc.com/pdf/progress/{batch_id}'
    )
    progress = progress_response.json()
    
    percentage = round((progress['current'] / progress['total']) * 100)
    print(f"Progress: {percentage}% ({progress['current']}/{progress['total']})")
    
    if progress['status'] == 'completed':
        result = json.loads(progress['message'])
        print(f"✅ Complete! Download: {result['downloadUrl']}")
        break
    elif progress['status'] == 'error':
        print(f"❌ Error: {progress['message']}")
        break
    
    time.sleep(2)  # Poll every 2 seconds
import fetch from 'node-fetch';
import EventSource from 'eventsource';

async function generateBatch() {
  // Start batch
  const response = await fetch('https://api.syntaxdoc.com/pdf/generate-batch', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.SYNTAXDOC_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      documents: Array.from({ length: 200 }, (_, i) => ({
        fileName: `document-${i + 1}`,
        htmlContent: `<html><body><h1>Document ${i + 1}</h1></body></html>`
      })),
      stream: true,
      host: true
    })
  });

  const { batchId } = await response.json();

  // Use SSE for real-time updates
  const eventSource = new EventSource(
    `https://api.syntaxdoc.com/pdf/progress/${batchId}/stream`
  );

  eventSource.addEventListener('progress', (event) => {
    const data = JSON.parse(event.data);
    process.stdout.write(
      `\r📄 Generated ${data.current}/${data.total} PDFs`
    );
  });

  eventSource.addEventListener('complete', (event) => {
    const data = JSON.parse(event.data);
    const result = JSON.parse(data.message);
    console.log('\n✅ Complete!');
    console.log('Download URL:', result.downloadUrl);
    eventSource.close();
  });
}

generateBatch();

Manage Hosted PDFs

List, view, and delete your hosted PDFs.

// List all hosted PDFs
const listResponse = await fetch('https://api.syntaxdoc.com/api/hosted-pdfs/list', {
  headers: { 'Authorization': 'Bearer YOUR_AUTH_TOKEN' }
});
const { hostedPdfs } = await listResponse.json();

console.log('Your hosted PDFs:');
hostedPdfs.forEach(pdf => {
  console.log(`- ${pdf.originalName} (${pdf.pdfId})`);
  console.log(`  URL: ${pdf.url}`);
  console.log(`  Expires: ${pdf.expiresAt}`);
});

// Get stats
const statsResponse = await fetch('https://api.syntaxdoc.com/api/hosted-pdfs/stats', {
  headers: { 'Authorization': 'Bearer YOUR_AUTH_TOKEN' }
});
const stats = await statsResponse.json();
console.log(`Used: ${stats.used}/${stats.limit} PDFs`);

// Delete a PDF
const deleteResponse = await fetch(`https://api.syntaxdoc.com/api/hosted-pdfs/${pdfId}`, {
  method: 'DELETE',
  headers: { 'Authorization': 'Bearer YOUR_AUTH_TOKEN' }
});

Multi-page Document with Page Breaks

Control page breaks in long documents.

<!DOCTYPE html>
<html>
<head>
  <style>
    body { font-family: Georgia, serif; line-height: 1.6; padding: 40px; }
    
    /* Force page break before each chapter */
    .chapter { page-break-before: always; }
    .chapter:first-child { page-break-before: avoid; }
    
    /* Avoid breaking inside these elements */
    .keep-together { page-break-inside: avoid; }
    
    /* Always break after table of contents */
    .toc { page-break-after: always; }
    
    h1 { color: #2c3e50; margin-bottom: 20px; }
    h2 { color: #34495e; margin-top: 30px; }
  </style>
</head>
<body>
  <div class="toc">
    <h1>Table of Contents</h1>
    <ol>
      <li>Introduction</li>
      <li>Getting Started</li>
      <li>Advanced Topics</li>
    </ol>
  </div>
  
  <div class="chapter">
    <h1>Chapter 1: Introduction</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
  </div>
  
  <div class="chapter">
    <h1>Chapter 2: Getting Started</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
    
    <div class="keep-together">
      <h2>Important Note</h2>
      <p>This section will not be split across pages.</p>
    </div>
  </div>
  
  <div class="chapter">
    <h1>Chapter 3: Advanced Topics</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
  </div>
</body>
</html>

Page break CSS properties:

  • page-break-before: always - Start on a new page
  • page-break-after: always - Break after this element
  • page-break-inside: avoid - Keep element together

On this page