4 Ways to Generate a PDF
APITemplate.io provides four distinct methods for generating PDFs. Each method serves different use cases — pick the one that fits your workflow.
| Method | Endpoint | Best for |
|---|---|---|
| Template-based | /v2/create-pdf | Reusable documents (invoices, reports, certificates) with dynamic data |
| Raw HTML | /v2/create-pdf-from-html | One-off PDFs where you control the full HTML and CSS |
| URL | /v2/create-pdf-from-url | Converting existing web pages to PDF |
| Markdown | /v2/create-pdf-from-markdown | Converting Markdown content to PDF |
All four methods share these capabilities:
- Custom headers and footers with page numbers
- Configurable margins, paper size, and orientation
- CSS and JavaScript rendering (Chromium-based)
- Synchronous and asynchronous generation
- Webhook notifications for async jobs
1. Generate a PDF from a template
Create a reusable template in the web console, then populate it with JSON data at generation time. This is the most common workflow for recurring documents like invoices, receipts, and reports.
API reference
| Endpoint | POST /v2/create-pdf |
| Query parameter | template_id (required) — the ID of your template |
| Request body | JSON object whose keys match the template's Jinja2 variables |
| Authentication | X-API-KEY header |
How it works
- Design a template in the HTML editor or visual editor.
- Add dynamic variables using Jinja2 syntax — for example
{{invoice_number}},{% for item in items %}. - Call the API with JSON data to fill in the variables.
- Receive a
download_urlfor the generated PDF.
Example request (cURL)
curl -X POST "https://rest.apitemplate.io/v2/create-pdf?template_id=YOUR_TEMPLATE_ID" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"date": "15/05/2024",
"invoice_no": "435568799",
"sender_address1": "3244 Jurong Drive",
"sender_address2": "Falmouth Maine 1703",
"sender_phone": "255-781-6789",
"sender_email": "hello@logos.com",
"items": [
{ "item_name": "Oil", "unit": 1, "unit_price": 100, "total": 100 },
{ "item_name": "Rice", "unit": 2, "unit_price": 200, "total": 400 }
],
"total": "500"
}'
Example request (C#)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async Task Main()
{
var url = "https://rest.apitemplate.io/v2/create-pdf?template_id=YOUR_TEMPLATE_ID";
var payload = new
{
date = "15/05/2024",
invoice_no = "435568799",
sender_address1 = "3244 Jurong Drive",
sender_address2 = "Falmouth Maine 1703",
sender_phone = "255-781-6789",
sender_email = "hello@logos.com",
items = new[]
{
new { item_name = "Oil", unit = 1, unit_price = 100, total = 100 },
new { item_name = "Rice", unit = 2, unit_price = 200, total = 400 },
},
total = "500",
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "YOUR_API_KEY");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
System.Console.WriteLine(result);
}
}
Example request (Python)
import requests
url = "https://rest.apitemplate.io/v2/create-pdf"
headers = {
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
}
params = {"template_id": "YOUR_TEMPLATE_ID"}
payload = {
"date": "15/05/2024",
"invoice_no": "435568799",
"sender_address1": "3244 Jurong Drive",
"sender_address2": "Falmouth Maine 1703",
"items": [
{"item_name": "Oil", "unit": 1, "unit_price": 100, "total": 100},
{"item_name": "Rice", "unit": 2, "unit_price": 200, "total": 400},
],
"total": "500",
}
response = requests.post(url, headers=headers, params=params, json=payload)
print(response.json())
Example response
{
"download_url": "https://rest.apitemplate.io/v2/get-pdf/...",
"transaction_ref": "8cd2aced-b2a2-40fb-bd45-392c777d6f6",
"status": "success",
"template_id": "YOUR_TEMPLATE_ID"
}
2. Generate a PDF from raw HTML
Send your own HTML, CSS, and data directly — no pre-built template needed. This is useful for one-off PDFs or when you generate HTML dynamically in your application.
API reference
| Endpoint | POST /v2/create-pdf-from-html |
| Request body fields | body (required) — HTML string |
css — CSS string | |
data — JSON object for Jinja2 variables inside body | |
settings — page configuration (see Settings below) | |
| Authentication | X-API-KEY header |
Example request (cURL)
curl -X POST "https://rest.apitemplate.io/v2/create-pdf-from-html" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "<h1>Hello {{name}}</h1><p>Your order has been confirmed.</p>",
"css": "<style>h1 { color: #2563eb; }</style>",
"data": {
"name": "World"
},
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10",
"print_background": "1"
}
}'
Example request (C#)
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async Task Main()
{
var data = new
{
body = "<h1>Hello {{name}}</h1><p>Your order has been confirmed.</p>",
css = "<style>h1 { color: #2563eb; }</style>",
data = new { name = "World" },
settings = new
{
paper_size = "A4",
orientation = "1",
margin_top = "40",
margin_right = "10",
margin_bottom = "40",
margin_left = "10",
print_background = "1",
}
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "YOUR_API_KEY");
var content = new StringContent(
JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://rest.apitemplate.io/v2/create-pdf-from-html", content);
var result = await response.Content.ReadAsStringAsync();
System.Console.WriteLine(result);
}
}
Example request (Python)
import requests
url = "https://rest.apitemplate.io/v2/create-pdf-from-html"
headers = {
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
}
payload = {
"body": "<h1>Hello {{name}}</h1><p>Your order has been confirmed.</p>",
"css": "<style>h1 { color: #2563eb; }</style>",
"data": {"name": "World"},
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10",
"print_background": "1",
},
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
Example response
{
"download_url": "https://rest.apitemplate.io/v2/get-pdf/...",
"transaction_ref": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "success"
}
3. Generate a PDF from a URL
Point the API at any publicly accessible web page and get a PDF back. The page is rendered in a headless Chromium browser, so JavaScript and modern CSS are fully supported.
API reference
| Endpoint | POST /v2/create-pdf-from-url |
| Request body fields | url (required) — the web page to convert |
settings — page configuration (see Settings below) | |
| Authentication | X-API-KEY header |
Example request (cURL)
curl -X POST "https://rest.apitemplate.io/v2/create-pdf-from-url" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://en.wikipedia.org/wiki/Main_Page",
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10",
"print_background": "1"
}
}'
Example request (C#)
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async Task Main()
{
var data = new
{
url = "https://en.wikipedia.org/wiki/Main_Page",
settings = new
{
paper_size = "A4",
orientation = "1",
margin_top = "40",
margin_right = "10",
margin_bottom = "40",
margin_left = "10",
print_background = "1",
displayHeaderFooter = true,
custom_header = "<div style='font-size:9px;text-align:center;width:100%'><span class='date'></span></div>",
custom_footer = "<div style='font-size:9px;text-align:center;width:100%'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>",
}
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "YOUR_API_KEY");
var content = new StringContent(
JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://rest.apitemplate.io/v2/create-pdf-from-url", content);
var result = await response.Content.ReadAsStringAsync();
System.Console.WriteLine(result);
}
}
Example request (Python)
import requests
url = "https://rest.apitemplate.io/v2/create-pdf-from-url"
headers = {
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
}
payload = {
"url": "https://en.wikipedia.org/wiki/Main_Page",
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10",
"print_background": "1",
},
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
Example response
{
"download_url": "https://rest.apitemplate.io/v2/get-pdf/...",
"transaction_ref": "f7e8d9c0-b1a2-3456-7890-abcdef012345",
"status": "success"
}
4. Generate a PDF from Markdown
Send Markdown content and get a PDF back. The API uses the marked library to parse Markdown into HTML, then renders it with the same Chromium-based engine used by the other methods. This is ideal when your content is already in Markdown — README files, knowledge-base articles, reports, or documentation.
API reference
| Endpoint | POST /v2/create-pdf-from-markdown |
| Request body fields | markdown (required) — Markdown string |
css — CSS string for styling the rendered output | |
data — JSON object for Jinja2 variables inside the Markdown | |
settings — page configuration (see Settings below) | |
| Authentication | X-API-KEY header |
Example request (cURL)
curl -X POST "https://rest.apitemplate.io/v2/create-pdf-from-markdown" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"markdown": "# Hello {{name}}\n\nRendered on **2024-05-15**.\n\n| Item | Qty | Price |\n|------|-----|-------|\n| Widget | 10 | $5.00 |\n| Gadget | 3 | $12.50 |",
"css": "<style>h1 { color: #2c3e50; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; }</style>",
"data": {
"name": "World"
},
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10"
}
}'
Example request (C#)
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async Task Main()
{
var data = new
{
markdown = "# Hello {{name}}\n\nRendered on **2024-05-15**.\n\n| Item | Qty | Price |\n|------|-----|-------|\n| Widget | 10 | $5.00 |\n| Gadget | 3 | $12.50 |",
css = "<style>h1 { color: #2c3e50; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; }</style>",
data = new { name = "World" },
settings = new
{
paper_size = "A4",
orientation = "1",
margin_top = "40",
margin_right = "10",
margin_bottom = "40",
margin_left = "10",
}
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "YOUR_API_KEY");
var content = new StringContent(
JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://rest.apitemplate.io/v2/create-pdf-from-markdown", content);
var result = await response.Content.ReadAsStringAsync();
System.Console.WriteLine(result);
}
}
Example request (Python)
import requests
url = "https://rest.apitemplate.io/v2/create-pdf-from-markdown"
headers = {
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
}
payload = {
"markdown": "# Hello {{name}}\n\nRendered on **2024-05-15**.\n\n| Item | Qty | Price |\n|------|-----|-------|\n| Widget | 10 | $5.00 |\n| Gadget | 3 | $12.50 |",
"css": "<style>h1 { color: #2c3e50; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; }</style>",
"data": {"name": "World"},
"settings": {
"paper_size": "A4",
"orientation": "1",
"margin_top": "40",
"margin_right": "10",
"margin_bottom": "40",
"margin_left": "10",
},
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
Example response
{
"download_url": "https://rest.apitemplate.io/v2/get-pdf/...",
"transaction_ref": "b3c4d5e6-f7a8-9012-bcde-f34567890abc",
"status": "success"
}
Settings object
The settings object is shared by the HTML, URL, and Markdown methods. Here are the most commonly used fields:
| Field | Type | Description |
|---|---|---|
paper_size | string | A4, Letter, Legal, or a custom size like 210mm x 297mm |
orientation | string | "1" for Portrait, "2" for Landscape |
margin_top | string | Top margin in pixels (e.g. "40") |
margin_right | string | Right margin in pixels |
margin_bottom | string | Bottom margin in pixels |
margin_left | string | Left margin in pixels |
print_background | string | "1" to include background colors/images |
displayHeaderFooter | boolean | true to render custom header/footer HTML |
custom_header | string | HTML for the page header |
custom_footer | string | HTML for the page footer |
header_font_size | string | Font size for the header (e.g. "9px") |
For header/footer HTML you can use these built-in CSS classes:
date— current datetitle— document titleurl— document URLpageNumber— current page numbertotalPages— total number of pages
See Headers and Footers for detailed examples.
Asynchronous generation
For large documents or batch jobs, add async=true as a query parameter:
curl -X POST "https://rest.apitemplate.io/v2/create-pdf?template_id=TEMPLATE_ID&async=true" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"company_name": "Acme Corp"}'
The response returns a transaction_ref immediately. Set up a webhook to be notified when the PDF is ready.
Regional endpoints
Choose the endpoint closest to your users:
| Region | Base URL |
|---|---|
| US (default) | https://rest.apitemplate.io/v2/ |
| EU | https://rest-eu.apitemplate.io/v2/ |
| Australia | https://rest-au.apitemplate.io/v2/ |
| Singapore | https://rest-sg.apitemplate.io/v2/ |
SDKs
Official client libraries handle authentication, serialization, and error handling for you:
| Language | Repository |
|---|---|
| C# | apitemplateio-csharp |
| Python | apitemplateio-python |
| JavaScript | apitemplateio-javascript |
| PHP | apitemplateio-php |
| Java | apitemplateio-java |
Which method should you choose?
- Template-based is ideal when you have a fixed layout that gets reused with different data — invoices, reports, certificates. You design the template once and the API fills it in.
- Raw HTML is best when your application dynamically generates the HTML, or you need a quick one-off PDF without setting up a template.
- URL-based is best for converting existing web pages — dashboards, articles, or any page that's already live.
- Markdown is best when your content is already written in Markdown — documentation, README files, knowledge-base articles, or reports. You skip the HTML authoring entirely and let the API handle the conversion.
Next steps
- Code/HTML Template Editor — build your first template
- Visual Template Editor — drag-and-drop editor for non-technical users
- Markdown to PDF blog post — in-depth guide with styling and template workflows
- REST API reference — full list of endpoints and parameters
- Full API Reference v2 — complete API documentation