Code Examples
Ready-to-use code snippets for integrating PDFShot into your application.
Basic Conversion
const response = await fetch('https://convert.pdfshot.com/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFSHOT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: '<h1>Hello World</h1>',
options: {
format: 'A4',
margin: '1in'
}
})
})
const data = await response.json()
if (data.success) {
console.log('PDF URL:', data.url)
} else {
console.error('Error:', data.error.message)
}
import os
import requests
response = requests.post(
'https://convert.pdfshot.com/convert',
headers={
'Authorization': f'Bearer {os.environ["PDFSHOT_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'html': '<h1>Hello World</h1>',
'options': {
'format': 'A4',
'margin': '1in'
}
}
)
data = response.json()
if data['success']:
print('PDF URL:', data['url'])
else:
print('Error:', data['error']['message'])
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload := map[string]interface{}{
"html": "<h1>Hello World</h1>",
"options": map[string]string{
"format": "A4",
"margin": "1in",
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://convert.pdfshot.com/convert",
bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("PDFSHOT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)
if data["success"].(bool) {
fmt.Println("PDF URL:", data["url"])
} else {
fmt.Println("Error:", data["error"])
}
}
require 'net/http'
require 'json'
require 'uri'
uri = URI('https://convert.pdfshot.com/convert')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV['PDFSHOT_API_KEY']}"
request['Content-Type'] = 'application/json'
request.body = {
html: '<h1>Hello World</h1>',
options: {
format: 'A4',
margin: '1in'
}
}.to_json
response = http.request(request)
data = JSON.parse(response.body)
if data['success']
puts "PDF URL: #{data['url']}"
else
puts "Error: #{data['error']['message']}"
end
<?php
$ch = curl_init('https://convert.pdfshot.com/convert');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('PDFSHOT_API_KEY'),
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode([
'html' => '<h1>Hello World</h1>',
'options' => [
'format' => 'A4',
'margin' => '1in'
]
])
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if ($data['success']) {
echo 'PDF URL: ' . $data['url'];
} else {
echo 'Error: ' . $data['error']['message'];
}
curl -X POST https://convert.pdfshot.com/convert \
-H "Authorization: Bearer $PDFSHOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Hello World</h1>",
"options": {
"format": "A4",
"margin": "1in"
}
}'
Converting a URL
Render a webpage to PDF:
const response = await fetch('https://convert.pdfshot.com/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFSHOT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://pdfshot.com/demo/invoice',
options: {
format: 'Letter',
printBackground: true
}
})
})
response = requests.post(
'https://convert.pdfshot.com/convert',
headers={
'Authorization': f'Bearer {os.environ["PDFSHOT_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'url': 'https://pdfshot.com/demo/invoice',
'options': {
'format': 'Letter',
'printBackground': True
}
}
)
payload := map[string]interface{}{
"url": "https://pdfshot.com/demo/invoice",
"options": map[string]interface{}{
"format": "Letter",
"printBackground": true,
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://convert.pdfshot.com/convert",
bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("PDFSHOT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
request.body = {
url: 'https://pdfshot.com/demo/invoice',
options: {
format: 'Letter',
printBackground: true
}
}.to_json
response = http.request(request)
$ch = curl_init('https://convert.pdfshot.com/convert');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('PDFSHOT_API_KEY'),
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://pdfshot.com/demo/invoice',
'options' => [
'format' => 'Letter',
'printBackground' => true
]
])
]);
$response = curl_exec($ch);
curl -X POST https://convert.pdfshot.com/convert \
-H "Authorization: Bearer $PDFSHOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://pdfshot.com/demo/invoice",
"options": {
"format": "Letter",
"printBackground": true
}
}'
Using Templates
Render a stored template with dynamic variables:
const response = await fetch('https://convert.pdfshot.com/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFSHOT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'your-template-id',
variables: {
customerName: 'Acme Corp',
invoiceNumber: 'INV-001',
items: [
{ name: 'Widget Pro', qty: 2, price: 50.00 },
{ name: 'Service Fee', qty: 1, price: 25.00 }
],
total: 125.00
},
options: { format: 'A4' }
})
})
const data = await response.json()
if (data.success) {
console.log('PDF URL:', data.url)
}
response = requests.post(
'https://convert.pdfshot.com/convert',
headers={
'Authorization': f'Bearer {os.environ["PDFSHOT_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'templateId': 'your-template-id',
'variables': {
'customerName': 'Acme Corp',
'invoiceNumber': 'INV-001',
'items': [
{'name': 'Widget Pro', 'qty': 2, 'price': 50.00},
{'name': 'Service Fee', 'qty': 1, 'price': 25.00}
],
'total': 125.00
},
'options': {'format': 'A4'}
}
)
data = response.json()
if data['success']:
print('PDF URL:', data['url'])
payload := map[string]interface{}{
"templateId": "your-template-id",
"variables": map[string]interface{}{
"customerName": "Acme Corp",
"invoiceNumber": "INV-001",
"items": []map[string]interface{}{
{"name": "Widget Pro", "qty": 2, "price": 50.00},
{"name": "Service Fee", "qty": 1, "price": 25.00},
},
"total": 125.00,
},
"options": map[string]string{"format": "A4"},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://convert.pdfshot.com/convert",
bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("PDFSHOT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
request.body = {
templateId: 'your-template-id',
variables: {
customerName: 'Acme Corp',
invoiceNumber: 'INV-001',
items: [
{ name: 'Widget Pro', qty: 2, price: 50.00 },
{ name: 'Service Fee', qty: 1, price: 25.00 }
],
total: 125.00
},
options: { format: 'A4' }
}.to_json
response = http.request(request)
data = JSON.parse(response.body)
puts "PDF URL: #{data['url']}" if data['success']
$ch = curl_init('https://convert.pdfshot.com/convert');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('PDFSHOT_API_KEY'),
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode([
'templateId' => 'your-template-id',
'variables' => [
'customerName' => 'Acme Corp',
'invoiceNumber' => 'INV-001',
'items' => [
['name' => 'Widget Pro', 'qty' => 2, 'price' => 50.00],
['name' => 'Service Fee', 'qty' => 1, 'price' => 25.00]
],
'total' => 125.00
],
'options' => ['format' => 'A4']
])
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if ($data['success']) {
echo 'PDF URL: ' . $data['url'];
}
curl -X POST https://convert.pdfshot.com/convert \
-H "Authorization: Bearer $PDFSHOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "your-template-id",
"variables": {
"customerName": "Acme Corp",
"invoiceNumber": "INV-001",
"items": [
{"name": "Widget Pro", "qty": 2, "price": 50.00},
{"name": "Service Fee", "qty": 1, "price": 25.00}
],
"total": 125.00
},
"options": {"format": "A4"}
}'
Create templates in your Dashboard. See the Templates Guide for Handlebars syntax and variable schema options.
Downloading the PDF
After getting the signed URL, download the file:
// Get the PDF
const pdfResponse = await fetch(data.url)
const pdfBuffer = await pdfResponse.arrayBuffer()
// Save to file (Node.js)
import { writeFile } from 'fs/promises'
await writeFile('output.pdf', Buffer.from(pdfBuffer))
// Or send to browser (browser/Nuxt)
const blob = new Blob([pdfBuffer], { type: 'application/pdf' })
const downloadUrl = URL.createObjectURL(blob)
window.open(downloadUrl, '_blank')
# Download the PDF
pdf_response = requests.get(data['url'])
# Save to file
with open('output.pdf', 'wb') as f:
f.write(pdf_response.content)
// Download the PDF
resp, _ := http.Get(data["url"].(string))
defer resp.Body.Close()
// Save to file
out, _ := os.Create("output.pdf")
defer out.Close()
io.Copy(out, resp.Body)
# Download the PDF
pdf_uri = URI(data['url'])
pdf_response = Net::HTTP.get(pdf_uri)
# Save to file
File.write('output.pdf', pdf_response)
// Download the PDF
$pdfContent = file_get_contents($data['url']);
// Save to file
file_put_contents('output.pdf', $pdfContent);
# Download the PDF using the URL from the response
curl -o output.pdf "$PDF_URL"
Invoice Template
A complete example generating an invoice:
const invoiceHtml = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 40px; }
.header { display: flex; justify-content: space-between; margin-bottom: 40px; }
.logo { font-size: 24px; font-weight: bold; }
.invoice-number { color: #666; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f9f9f9; }
.total { font-size: 18px; font-weight: bold; text-align: right; }
</style>
</head>
<body>
<div class="header">
<div class="logo">ACME Corp</div>
<div class="invoice-number">Invoice #12345</div>
</div>
<table>
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Widget Pro</td>
<td>2</td>
<td>$50.00</td>
</tr>
<tr>
<td>Service Fee</td>
<td>1</td>
<td>$25.00</td>
</tr>
</tbody>
</table>
<div class="total">Total: $125.00</div>
</body>
</html>
`
const response = await fetch('https://convert.pdfshot.com/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFSHOT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: invoiceHtml,
options: {
format: 'Letter',
margin: '0.75in',
printBackground: true
}
})
})
Error Handling
Always handle errors gracefully:
async function convertToPdf(html, options = {}) {
try {
const response = await fetch('https://convert.pdfshot.com/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFSHOT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ html, options })
})
const data = await response.json()
if (!data.success) {
throw new Error(`${data.error.code}: ${data.error.message}`)
}
return data.url
} catch (error) {
console.error('PDF conversion failed:', error.message)
throw error
}
}
Retry with Backoff
For production systems, implement retry logic:
async function convertWithRetry(html, options = {}, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await convertToPdf(html, options)
} catch (error) {
if (attempt === maxRetries) throw error
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt - 1) * 1000
await new Promise(resolve => setTimeout(resolve, delay))
}
}
}