Skip to main content

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.

MethodEndpointBest for
Template-based/v2/create-pdfReusable documents (invoices, reports, certificates) with dynamic data
Raw HTML/v2/create-pdf-from-htmlOne-off PDFs where you control the full HTML and CSS
URL/v2/create-pdf-from-urlConverting existing web pages to PDF
Markdown/v2/create-pdf-from-markdownConverting 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

EndpointPOST /v2/create-pdf
Query parametertemplate_id (required) — the ID of your template
Request bodyJSON object whose keys match the template's Jinja2 variables
AuthenticationX-API-KEY header

How it works

  1. Design a template in the HTML editor or visual editor.
  2. Add dynamic variables using Jinja2 syntax — for example {{invoice_number}}, {% for item in items %}.
  3. Call the API with JSON data to fill in the variables.
  4. Receive a download_url for 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

EndpointPOST /v2/create-pdf-from-html
Request body fieldsbody (required) — HTML string
css — CSS string
data — JSON object for Jinja2 variables inside body
settings — page configuration (see Settings below)
AuthenticationX-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

EndpointPOST /v2/create-pdf-from-url
Request body fieldsurl (required) — the web page to convert
settings — page configuration (see Settings below)
AuthenticationX-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

EndpointPOST /v2/create-pdf-from-markdown
Request body fieldsmarkdown (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)
AuthenticationX-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:

FieldTypeDescription
paper_sizestringA4, Letter, Legal, or a custom size like 210mm x 297mm
orientationstring"1" for Portrait, "2" for Landscape
margin_topstringTop margin in pixels (e.g. "40")
margin_rightstringRight margin in pixels
margin_bottomstringBottom margin in pixels
margin_leftstringLeft margin in pixels
print_backgroundstring"1" to include background colors/images
displayHeaderFooterbooleantrue to render custom header/footer HTML
custom_headerstringHTML for the page header
custom_footerstringHTML for the page footer
header_font_sizestringFont size for the header (e.g. "9px")

For header/footer HTML you can use these built-in CSS classes:

  • date — current date
  • title — document title
  • url — document URL
  • pageNumber — current page number
  • totalPages — 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:

RegionBase URL
US (default)https://rest.apitemplate.io/v2/
EUhttps://rest-eu.apitemplate.io/v2/
Australiahttps://rest-au.apitemplate.io/v2/
Singaporehttps://rest-sg.apitemplate.io/v2/

SDKs

Official client libraries handle authentication, serialization, and error handling for you:

LanguageRepository
C#apitemplateio-csharp
Pythonapitemplateio-python
JavaScriptapitemplateio-javascript
PHPapitemplateio-php
Javaapitemplateio-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