Templates
This guide walks you through template concepts, provides real-world examples and common use cases, explains the complete workflow, and helps you get started with templates.
What are Templates?
Templates are reusable HTML layouts powered by templating engines that enable you to generate dynamic PDFs by combining a predefined design with variable data. Think of templates as smart document blueprints where you design the layout once and then populate it with different data for each PDF generation.
Template Overview
Instead of sending complete HTML content for each PDF generation, templates use a clean separation approach:
-
Template Definition – Create an HTML layout with placeholders (variables) using Handlebars syntax:
- Use AI Template Generation – just describe what you need or attach reference files.
- Choose from our professionally designed gallery of ready-to-use templates.
- Or design your own template from scratch using our visual designer.
-
Data Injection – Send only the template ID and JSON data payload to our API to generate personalized PDFs:
- The JSON data gets automatically merged with your template.
- You can integrate this from any programming language – Node.js, Python, PHP, Java, C#, Go, Rust, etc. or use simple cURL commands.
Template data is not stored – it's only used for PDF generation and immediately discarded.
Your data remains private and secure.
PDFBolt uses Handlebars – a powerful and widely-adopted templating engine that extends HTML with dynamic capabilities:
- Variable Substitution –
{{customerName}}gets replaced with actual customer data. - Conditional Logic –
{{#if isPaid}}...{{/if}}shows content based on conditions. - Loops & Iteration –
{{#each items}}...{{/each}}repeats content for arrays. - Nested Objects – Access deep data structures like
{{customer.address.city}}.
Learn more about Handlebars templating syntax in the official Handlebars documentation.
We currently support Handlebars, but if you have a specific template engine in mind, contact us at contact@pdfbolt.com and we'll consider adding engines based on your needs.
Simple Example: Template Transformation
This basic example demonstrates the core concept – see the full invoice example below.
📝 Template HTML (with Handlebars):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Invoice #{{invoiceNumber}}</title>
<style>
.invoice { margin: 40px; }
.status.paid { color: green; }
.status.pending { color: orange; }
</style>
</head>
<body>
<div class="invoice">
<h1>Invoice #{{invoiceNumber}}</h1>
<p>Dear {{customer.name}},</p>
<div class="items">
{{#each items}}
<p class="item">
{{name}}: ${{price}}
</p>
{{/each}}
</div>
{{#if isPaid}}
<p class="status paid">✅ PAID</p>
{{else}}
<p class="status pending">PENDING</p>
{{/if}}
<p><strong>Total: ${{total}}</strong></p>
</div>
</body>
</html>
📊 JSON Data Used:
{
"invoiceNumber": "INV-001",
"customer": {"name": "John Doe"},
"items": [
{"name": "Premium Service", "price": "199.99"},
{"name": "Setup Fee", "price": "99.99"}
],
"isPaid": true,
"total": "299.98"
}
📋 Final PDF Result:

Key Benefits
Templates transform how you generate PDFs by separating design from data, making document creation more efficient, consistent, and maintainable. Here are the key advantages of using PDFBolt's template system:
Simplified API Calls
- Cleaner Code – Send only
templateIdandtemplateDatainstead of complete HTML content. - Easier Debugging – The template and data are completely separate.
Consistent Design
- Version Control – Update template design in one place – changes instantly apply to all future PDFs.
- Eliminates Errors – No more formatting mistakes or inconsistent styling across documents.
Faster Development
- AI-Powered Creation – Skip the coding. Generate templates with AI from descriptions and example files.
- Ready-to-Use Gallery – Start with ready-made designs for invoices, reports, certificates, resumes, and more.
- Visual Designer – Build and test templates with real-time preview.
- Developer-Friendly – Handlebars syntax familiar to most developers, ready-to-use code snippets.
Flexible Data Handling
- Smart Data Binding – Handlebars automatically handles complex data structures, arrays, and nested objects.
- Conditional Logic – Show/hide content based on data values (
{{#if}},{{#unless}}).
Team Efficiency
- Team Collaboration – Manage templates across your organization.
- Scalable Solution – Handle growing document volume without additional infrastructure.
Common Use Cases
Whether it's automated billing or personalized certificates, templates streamline document generation across your business needs.
Business Operations
Invoices, Receipts, Purchase Orders, Quotes, Statements
Analytics & Reporting
Financial reports, KPI dashboards, Performance reviews, Executive summaries
Education & Human Resources
Certificates, Course completion, Employee handbooks, Offer letters, Performance evaluations
Customer Communications
Personalized letters, Product catalogs, Support tickets, Shipping labels
Legal & Compliance
Contracts, Agreements, Policy documents, Audit reports
Sales & Marketing
Sales proposals, Product sheets, Marketing brochures, Event materials
How Templates Work
Templates follow a simple workflow that separates design from data, making PDF generation scalable and maintainable:
1. Template Creation
- Design your HTML layout using our visual designer, generate with AI from your description and attached files, or choose from our template gallery.
- Add Handlebars variables (
{{variableName}}) for dynamic content insertion. - Include conditional logic (
{{#if}}) and loops ({{#each}}) for complex document structures. - Preview with sample data using quick HTML preview and generate real PDFs to verify the final output.
- You can also duplicate templates for variations and save drafts automatically.
See the full template creation and management guide.
2. Template Publishing
- Publish your template to make it available via API endpoints.
- Get your unique template ID for seamless integration.
- Built-in version control allows you to roll back changes safely.
See more about template publishing.
3. PDF Generation
- Access ready-to-use code snippets for multiple programming languages (Node.js, Python, PHP, Java, C#, Go, Rust).
- Send a lightweight API request containing only your template ID and JSON data.
- Our high-performance engine merges your data with the template automatically.
Explore API integration examples and API endpoints.
4. Receive Results
- Receive professional, high-quality PDFs ready for download, email, or storage.
- Scale effortlessly to generate millions of documents without performance bottlenecks.

See the full list of PDF customization options.
Complete Example: From Template to PDF
See how templates transform complex document generation into a simple API call. This professional invoice example demonstrates the full power of PDFBolt's template system:
1. Create your HTML template with Handlebars variables and logic (or generate with AI / choose from template gallery):
Example Template Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Invoice - {{invoice_number}}</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Dancing+Script:wght@700&display=swap');
:root {
/* Brand Colors */
--accent-color: #b8577e;
/* Text Colors */
--text-primary: #333;
--text-secondary: #555;
--text-white: #fff;
--text-muted: #777;
/* Background Colors */
--bg-primary: #ffffff;
--bg-secondary: #fafafa;
--bg-accent: #f9f9f9;
/* Border Colors */
--border-light: #e9e9e9;
--border-medium: #ddd;
--border-dark: #ccc;
/* Font Sizes */
--font-size-xs: 12px;
--font-size-sm: 13px;
--font-size-base: 14px;
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-2xl: 20px;
--font-size-3xl: 24px;
--font-size-4xl: 54px;
--font-size-5xl: 72px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
color: var(--text-primary);
font-family: 'Inter', sans-serif;
line-height: 1.7;
font-size: var(--font-size-base);
}
.invoice-container {
background: var(--bg-primary);
padding: 55px;
}
.invoice-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 25px;
gap: 20px;
}
.company-section {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.company-logo {
max-width: 80px;
height: auto;
object-fit: contain;
}
.company-name {
margin-top: 8px;
font-size: var(--font-size-2xl);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 2px;
}
.invoice-title-section {
text-align: right;
}
.invoice-title,
.thank-you-message {
font-family: 'Dancing Script', cursive;
color: var(--accent-color);
font-weight: 700;
line-height: 1;
}
.invoice-title {
font-size: var(--font-size-5xl);
margin-bottom: 10px;
}
.invoice-meta,
.billing-details,
.payment-info-item,
.total-label {
font-size: var(--font-size-base);
color: var(--text-secondary);
}
.invoice-meta-label,
.payment-info-label,
.billing-name,
.total-amount {
font-weight: 600;
color: var(--text-primary);
}
.billing-section,
.summary-section {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
gap: 30px;
flex-wrap: wrap;
}
.billing-block {
padding: 0 8px;
flex: 1;
color: var(--text-secondary);
}
.billing-title,
.payment-info-title {
color: var(--accent-color);
font-size: var(--font-size-lg);
font-weight: 600;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.invoice-meta,
.billing-name,
.payment-info-item {
margin-bottom: 4px;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
color: var(--text-secondary);
}
.table-header {
background: var(--accent-color);
color: var(--text-white);
}
.items-table th {
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.items-table th,
.items-table td {
padding: 10px 14px;
font-size: var(--font-size-base);
border-bottom: 1px solid var(--border-medium);
text-align: right;
}
.items-table th:first-child,
.items-table td:first-child {
text-align: left;
}
.payment-info-section {
flex: 1;
margin-top: 12px;
}
.payment-info-section,
.totals-section {
width: 48%;
}
.total-row {
display: flex;
justify-content: space-between;
padding: 10px 4px;
font-size: var(--font-size-base);
align-items: center;
border-bottom: 1px solid var(--border-medium);
}
.total-row-final {
font-weight: 700;
color: var(--accent-color);
border-top: 1.5px solid var(--accent-color);
font-size: var(--font-size-lg);
}
.totals-section .total-row:last-child {
border-bottom: none;
}
.total-row-final .total-amount {
color: var(--accent-color);
}
.thank-you-section {
text-align: center;
margin: 20px 0;
}
.thank-you-message {
font-size: var(--font-size-4xl);
}
@page {
margin: 1.5cm;
}
@media print {
.invoice-container {
padding: 0;
}
.invoice-header,
.billing-section,
.summary-section,
.items-table tr {
page-break-inside: avoid;
}
}
</style>
</head>
<body>
<div class="invoice-container">
<!-- Header section - company logo, name, and invoice details -->
<div class="invoice-header">
<div class="company-section">
{{#if company_logo_url}}
<img src="{{company_logo_url}}" alt="{{company_name}} Logo" class="company-logo"/>
{{/if}}
<div class="company-name">{{company_name}}</div>
</div>
<div class="invoice-title-section">
<h1 class="invoice-title">Invoice</h1>
<div class="invoice-meta">
<p><span class="invoice-meta-label">Invoice No:</span> {{invoice_number}}</p>
<p><span class="invoice-meta-label">Issue Date:</span> {{issue_date}}</p>
{{#if due_date}}
<p><span class="invoice-meta-label">Due Date:</span> {{due_date}}</p>
{{/if}}
</div>
</div>
</div>
<!-- Billing section -->
<div class="billing-section">
<div class="billing-block">
<h2 class="billing-title">Billed from</h2>
<p class="billing-name">{{company_name}}</p>
<div class="billing-details">
{{#if company_address_street}}
<p>{{company_address_street}}</p>
{{/if}} {{#if company_address_line2}}
<p>{{company_address_line2}}</p>
{{/if}}{{#if company_city}}
<p>
{{company_city}}{{#if company_state}}, {{company_state}}{{/if}}{{#if company_postal_code}}
{{company_postal_code}}{{/if}}{{#if company_country}}, {{company_country}}{{/if}}
</p>
{{/if}} {{#if company_email}}
<p>{{company_email}}</p>
{{/if}} {{#if company_phone}}
<p>{{company_phone}}</p>
{{/if}} {{#if company_tax_id}}
<p>Tax ID: {{company_tax_id}}</p>
{{/if}}
</div>
</div>
<div class="billing-block">
<h2 class="billing-title">Billed to</h2>
<p class="billing-name">{{client_name}}</p>
<div class="billing-details">
{{#if client_address_street}}
<p>{{client_address_street}}</p>
{{/if}} {{#if client_address_line2}}
<p>{{client_address_line2}}</p>
{{/if}}{{#if client_city}}
<p>
{{client_city}}{{#if client_state}}, {{client_state}}{{/if}}{{#if client_postal_code}}
{{client_postal_code}}{{/if}}{{#if client_country}}, {{client_country}}{{/if}}
</p>
{{/if}} {{#if client_email}}
<p>{{client_email}}</p>
{{/if}} {{#if client_phone}}
<p>{{client_phone}}</p>
{{/if}} {{#if client_tax_id}}
<p>Tax ID: {{client_tax_id}}</p>
{{/if}}
</div>
</div>
</div>
<!-- Products/services table -->
<table class="items-table">
<thead class="table-header">
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{{#each line_items}}
<tr>
<td class="item-description">{{this.description}}</td>
<td>{{this.quantity}}</td>
<td>{{../currency_symbol}}{{this.unit_price}}</td>
<td>{{../currency_symbol}}{{this.total_amount}}</td>
</tr>
{{/each}}
</tbody>
</table>
<!-- Payment Details -->
<div class="summary-section">
<div class="payment-info-section">
<h3 class="payment-info-title">Payment Information</h3>
{{#if payment_info.bank_name}}
<div class="payment-info-item">
<span class="payment-info-label">Bank Name:</span> {{payment_info.bank_name}}
</div>
{{/if}} {{#if payment_info.account_number}}
<div class="payment-info-item">
<span class="payment-info-label">Account No:</span> {{payment_info.account_number}}
</div>
{{/if}} {{#if payment_info.routing_number}}
<div class="payment-info-item">
<span class="payment-info-label">Routing:</span> {{payment_info.routing_number}}
</div>
{{/if}} {{#if payment_info.payment_terms}}
<div class="payment-info-item">
<span class="payment-info-label">Terms:</span> {{payment_info.payment_terms}}
</div>
{{/if}}
</div>
<!-- Invoice totals and calculations -->
<div class="totals-section">
<div class="total-row">
<span class="total-label">Subtotal</span>
<span class="total-amount">{{currency_symbol}}{{subtotal_amount}}</span>
</div>
{{#if discount_amount}}
<div class="total-row">
<span class="total-label">Discount{{#if discount_percentage}} ({{discount_percentage}}%){{/if}}</span>
<span class="total-amount">-{{currency_symbol}}{{discount_amount}}</span>
</div>
{{/if}} {{#if tax_amount}}
<div class="total-row">
<span class="total-label">Tax{{#if tax_percentage}} ({{tax_percentage}}%){{/if}}</span>
<span class="total-amount">{{currency_symbol}}{{tax_amount}}</span>
</div>
{{/if}}
<div class="total-row total-row-final">
<span class="total-label">Total Amount</span>
<span class="total-amount">{{currency_symbol}}{{total_amount}}</span>
</div>
</div>
</div>
<div class="thank-you-section">
<h3 class="thank-you-message">Thank you!</h3>
</div>
</div>
</body>
</html>
2. Send your API request with template ID and data (cURL example):
curl 'https://api.pdfbolt.com/v1/direct' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"templateId": "your-template-id",
"templateData": {"invoice_number":"INV-2025-014","issue_date":"June 13, 2025","due_date":"June 27, 2025","company_name":"Pink Brand Studio","company_email":"pink@example.com","company_phone":"+1 (555) 222-3344","company_address_street":"22 Rose Garden Lane","company_city":"Blushville","company_state":"CA","company_postal_code":"90210","company_country":"USA","company_tax_id":"PB-2025-001","company_logo_url":"https://img.pdfbolt.com/business-logo-template.png","client_name":"Luxe Beauty Co.","client_email":"contact@example.com","client_phone":"+1 (555) 667-8899","client_address_street":"88 Glamour Ave","client_city":"Glowtown","client_state":"NY","client_postal_code":"10001","client_country":"USA","client_tax_id":"LB-9988","line_items":[{"description":"Brand Identity Package","quantity":1,"unit_price":"600.00","total_amount":"600.00"},{"description":"Custom Instagram Templates","quantity":1,"unit_price":"200.00","total_amount":"200.00"},{"description":"Product Photography Session","quantity":1,"unit_price":"350.00","total_amount":"350.00"},{"description":"E-commerce Banner Design","quantity":2,"unit_price":"75.00","total_amount":"150.00"},{"description":"Email Newsletter Template","quantity":1,"unit_price":"120.00","total_amount":"120.00"}],"payment_info":{"bank_name":"Example Bank","account_number":"1234567890123456","routing_number":"110099001","payment_terms":"Due in 14 days"},"currency_symbol":"$","subtotal_amount":"1420.00","discount_percentage":"10","discount_amount":"142.00","tax_percentage":"20","tax_amount":"255.60","total_amount":"1533.60"}
}' \
--output invoice.pdf
3. Receive your generated PDF:

Generated invoice PDF with dynamic data and branded styling.
Frequently Asked Questions
Do I need coding knowledge to use Templates?
Not necessarily! You can:
- Use AI Template Generation to create templates from descriptions or reference files – no coding required.
- Start with ready-made templates from our gallery and customize them for your brand.
- Use our visual designer with real-time preview.
- Handlebars syntax is simple – use
{{variableName}}for data insertion.
Can I modify published templates?
Yes! Edit templates to create new drafts, preview changes, and publish new versions when ready. Built-in version control lets you compare changes and roll back safely.
What happens to my template data during PDF generation?
Template data is not stored – it's only used for PDF generation and immediately discarded. Your data remains private and secure.
Can I use custom fonts in my templates?
Yes! Import custom fonts via Google Fonts or any external font URL directly in your template. For example, using CSS @import:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
Or using a <link> tag in your template's <head>:
<link href="https://fonts.googleapis.com/css2?family=Titillium+Web:wght@400;600;700&display=swap" rel="stylesheet" />
Can I pass HTML content in template data?
Yes! By default, Handlebars escapes HTML in variables for security. To render raw HTML from your data, use triple curly braces {{{variable}}} instead of double {{variable}}. For example:
{
"description": "<strong>Bold text</strong> and <em>italic</em>"
}
<!-- Unescaped (renders actual HTML) -->
<p>{{{description}}}</p>
Result in the generated PDF:
Bold text and italic
Can I use images in my templates?
Yes! You can include images using:
- External URLs – reference any publicly accessible image:
<img src="https://example.com/logo.png" /> - Base64 encoding – embed images directly in your template:
<img src="data:image/png;base64,..." /> - Dynamic images – pass image URLs in your template data using Handlebars:
<img src="{{companyLogo}}" /> - Inline SVG – embed SVG graphics directly in your HTML for sharp, scalable icons and logos
How do I control page breaks in templates?
Use CSS print properties to control page breaks:
/* Force a page break before an element */
.new-page { page-break-before: always; }
/* Prevent an element from being split across pages */
.keep-together { break-inside: avoid; }
/* Force a page break after an element */
.section-end { page-break-after: always; }
This is especially useful for long tables or multi-section documents. See our optimizing HTML for PDF guide for more examples.
Can I add headers and footers to template PDFs?
Yes! Enable Display Header & Footer in the template's PDF Options tab. You can use built-in variables like page number and total pages. See the parameters documentation for details.
How do I style my templates?
Write your styles directly in the template using one of these approaches:
<style> block in your template's <head>:
<style>
.invoice-title { font-size: 24px; font-weight: bold; color: #333; }
.total { text-align: right; border-top: 2px solid #000; }
</style>
Inline styles directly on HTML elements:
<h1 style="font-size: 24px; font-weight: bold; color: #333;">Invoice</h1>
You can combine both approaches in the same template.
Can I use JavaScript in my templates?
Yes! Templates are rendered by a full browser engine, so JavaScript works. Use waitUntil: "networkidle" to wait for all external scripts to load, or waitForFunction for more precise control over when the PDF is generated.
For example, generating a QR code with an external library:
{{#if qr_code_data}}
<canvas id="qr-code"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js"></script>
<script>
new QRious({
element: document.getElementById('qr-code'),
value: '{{qr_code_data}}'
});
</script>
{{/if}}
How can I test my template before going live?
The template designer offers two preview modes:
- Quick HTML Preview – instant visual feedback as you edit.
- Real PDF Preview – generates an actual PDF using the API engine, so you can verify the final output including page breaks, fonts, and print styles.
Your template stays in draft until you publish it, so you can test freely without affecting production.
Do you support other templating engines besides Handlebars?
We currently support the Handlebars templating engine, but if you're looking for a different one, contact us at contact@pdfbolt.com and we'll consider adding engines based on user needs.
Additional Resources
Explore these resources for detailed implementation:
📄️ AI Template Generation
Create and edit templates with AI using prompts
📄️ PDF Templates Gallery
Ready-to-use professional templates for common documents
📄️ Conversion Parameters
Reference for templateId, templateData and PDF options
📄️ API Endpoints
Different endpoints for various PDF generation methods
📄️ Quick Start Guide
Code snippets for all major programming languages
📄️ Template Management
Complete template creation and management workflow