API Documentation
Generate PDFs, invoices, and QR codes with a single API call. Track QR scans with real-time analytics. Host pages and forms.
curl -X POST https://apresskit.app/v1/pdf/generate \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"content": "# Hello World\nYour first PDF.", "content_type": "markdown"}' \
-o hello.pdf
Authentication
API Key auth — for document generation endpoints (/v1/pdf/*, /v1/invoice/*, /v1/qr/*):
- Create an account at /dashboard/register
- Verify your email (click the magic link)
- Go to Dashboard → API Keys → Create Key
- Use the key in the
Authorizationheader:
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
JWT auth — for tracked QR and pages endpoints (/v1/qr-track/*, /v1/pages/*):
Use the access_token returned from POST /auth/login or POST /auth/register.
Endpoints
Document Generation (API Key)
Convert HTML or Markdown content into a styled PDF document. Supports custom CSS and page sizes.
{
"content": "<h1>Hello World</h1><p>Your content here.</p>",
"content_type": "html",
"css": null,
"page_size": "letter",
"filename": "document.pdf"
}curl -X POST https://apresskit.app/v1/pdf/generate \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"content": "<h1>Hello</h1><p>World</p>",
"content_type": "html",
"page_size": "letter",
"filename": "report.pdf"
}' -o report.pdf
import requests
resp = requests.post(
"https://apresskit.app/v1/pdf/generate",
headers={"Authorization": "Bearer pk_live_xxxx"},
json={
"content": "<h1>Hello</h1><p>World</p>",
"content_type": "html",
"page_size": "letter",
"filename": "report.pdf",
},
)
with open("report.pdf", "wb") as f:
f.write(resp.content)
const resp = await fetch("https://apresskit.app/v1/pdf/generate", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_xxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "<h1>Hello</h1><p>World</p>",
content_type: "html",
page_size: "letter",
filename: "report.pdf",
}),
});
const blob = await resp.blob();
application/pdf — Max input: 5MB, max output: 10MB. Supports html or markdown content_type. Page sizes: letter, a4, legal.Generate a professional invoice PDF from structured JSON data. Includes vendor/client info, line items, tax calculation, and notes.
{
"vendor": {"name": "Acme Corp", "address": "123 Main St", "email": "billing@acme.com"},
"client": {"name": "Client Inc", "address": "456 Oak Ave", "email": "pay@client.com"},
"invoice_number": "INV-2026-042",
"date": "2026-04-08",
"due_date": "2026-05-08",
"currency": "USD",
"line_items": [
{"description": "QR Marketing Setup", "quantity": 1, "unit_price": 500.00},
{"description": "Monthly Management", "quantity": 3, "unit_price": 150.00}
],
"tax_rate": 0.13,
"notes": "Payment due within 30 days.",
"template": "default",
"filename": "invoice-042.pdf"
}curl -X POST https://apresskit.app/v1/invoice/create \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"vendor": {"name": "Acme Corp"},
"client": {"name": "Client Inc"},
"invoice_number": "INV-001",
"line_items": [{"description": "Service", "quantity": 1, "unit_price": 100}],
"tax_rate": 0.13,
"template": "default"
}' -o invoice.pdf
import requests
resp = requests.post(
"https://apresskit.app/v1/invoice/create",
headers={"Authorization": "Bearer pk_live_xxxx"},
json={
"vendor": {"name": "Acme Corp", "email": "billing@acme.com"},
"client": {"name": "Client Inc"},
"invoice_number": "INV-001",
"line_items": [
{"description": "QR Marketing Setup", "quantity": 1, "unit_price": 500},
{"description": "Monthly Mgmt", "quantity": 3, "unit_price": 150},
],
"tax_rate": 0.13,
"template": "default",
},
)
with open("invoice.pdf", "wb") as f:
f.write(resp.content)
const resp = await fetch("https://apresskit.app/v1/invoice/create", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_xxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
vendor: { name: "Acme Corp" },
client: { name: "Client Inc" },
invoice_number: "INV-001",
line_items: [{ description: "Service", quantity: 1, unit_price: 100 }],
tax_rate: 0.13,
template: "default",
}),
});
const blob = await resp.blob();
application/pdf — Templates: default, minimal. Tax is auto-calculated from rate. Totals computed server-side.Generate a QR code image from any text or URL. Customize size, colors, format, and error correction level.
{
"data": "https://example.com",
"size": 512,
"format": "png",
"error_correction": "M",
"foreground": "#000000",
"background": "#FFFFFF"
}curl -X POST https://apresskit.app/v1/qr/generate \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"data": "https://example.com", "size": 512, "format": "png"}' \
-o qrcode.png
import requests
resp = requests.post(
"https://apresskit.app/v1/qr/generate",
headers={"Authorization": "Bearer pk_live_xxxx"},
json={
"data": "https://example.com",
"size": 512,
"format": "png",
"foreground": "#1a1a1a",
"background": "#ffffff",
},
)
with open("qrcode.png", "wb") as f:
f.write(resp.content)
const resp = await fetch("https://apresskit.app/v1/qr/generate", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_xxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
data: "https://example.com",
size: 512,
format: "png",
}),
});
const blob = await resp.blob();
image/png or image/svg+xml — Size: 64-4000px. Error correction: L (7%), M (15%), Q (25%), H (30%).Generate a QR code with a logo image centered on it. Uses multipart form data. Automatically uses H (30%) error correction to compensate for the logo overlay.
curl -X POST https://apresskit.app/v1/qr/generate-with-logo \
-H "Authorization: Bearer pk_live_xxxx" \
-F "data=https://example.com" \
-F "size=512" \
-F "foreground=#000000" \
-F "background_color=#FFFFFF" \
-F "logo=@mylogo.png" \
-o qrcode-logo.png
import requests
with open("mylogo.png", "rb") as logo:
resp = requests.post(
"https://apresskit.app/v1/qr/generate-with-logo",
headers={"Authorization": "Bearer pk_live_xxxx"},
data={
"data": "https://example.com",
"size": "512",
"foreground": "#000000",
"background_color": "#FFFFFF",
},
files={"logo": ("logo.png", logo, "image/png")},
)
with open("qrcode-logo.png", "wb") as f:
f.write(resp.content)
const formData = new FormData();
formData.append("data", "https://example.com");
formData.append("size", "512");
formData.append("logo", logoFile); // File object
const resp = await fetch("https://apresskit.app/v1/qr/generate-with-logo", {
method: "POST",
headers: { "Authorization": "Bearer pk_live_xxxx" },
body: formData,
});
const blob = await resp.blob();
image/png — Multipart form upload. Logo max: 1MB. Always uses H error correction. PNG output only.Generate a thermal-style receipt PDF from structured JSON data. Ideal for POS systems, e-commerce confirmations, and food service.
{
"vendor": {"name": "Joe's Coffee", "address": "123 Main St", "phone": "555-0100"},
"receipt_number": "R-2026-0042",
"date": "2026-04-08",
"currency": "USD",
"items": [
{"description": "Espresso", "quantity": 2, "unit_price": 3.50},
{"description": "Croissant", "quantity": 1, "unit_price": 4.00}
],
"tax_rate": 0.05,
"payment_method": "Card",
"cashier": "Maria",
"notes": "Loyalty points earned: 11"
}curl -X POST https://apresskit.app/v1/receipt/create \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"vendor": {"name": "Joe Coffee"},
"items": [{"description": "Latte", "quantity": 1, "unit_price": 5.00}],
"tax_rate": 0.05
}' -o receipt.pdf
import requests
resp = requests.post(
"https://apresskit.app/v1/receipt/create",
headers={"Authorization": "Bearer pk_live_xxxx"},
json={
"vendor": {"name": "Joe Coffee", "phone": "555-0100"},
"items": [
{"description": "Espresso", "quantity": 2, "unit_price": 3.50},
{"description": "Croissant", "quantity": 1, "unit_price": 4.00},
],
"tax_rate": 0.05,
"payment_method": "Card",
},
)
with open("receipt.pdf", "wb") as f:
f.write(resp.content)
const resp = await fetch("https://apresskit.app/v1/receipt/create", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_xxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
vendor: { name: "Joe Coffee" },
items: [{ description: "Latte", quantity: 1, unit_price: 5.00 }],
tax_rate: 0.05,
}),
});
const blob = await resp.blob();
application/pdf — Thermal receipt style (80mm width). Tax auto-calculated. Optional: cashier, payment method, notes.Generate standard barcodes as PNG or SVG images. Supports Code128, EAN-13, EAN-8, UPC-A, Code39, and ISBN-13.
{
"data": "5901234123457",
"barcode_type": "ean13",
"format": "png",
"width": 400,
"height": 150,
"show_text": true
}curl -X POST https://apresskit.app/v1/barcode/generate \
-H "Authorization: Bearer pk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"data": "ITEM-12345", "barcode_type": "code128", "format": "png"}' \
-o barcode.png
import requests
resp = requests.post(
"https://apresskit.app/v1/barcode/generate",
headers={"Authorization": "Bearer pk_live_xxxx"},
json={
"data": "5901234123457",
"barcode_type": "ean13",
"format": "png",
"show_text": True,
},
)
with open("barcode.png", "wb") as f:
f.write(resp.content)
const resp = await fetch("https://apresskit.app/v1/barcode/generate", {
method: "POST",
headers: {
"Authorization": "Bearer pk_live_xxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
data: "ITEM-12345",
barcode_type: "code128",
format: "png",
}),
});
const blob = await resp.blob();
image/png or image/svg+xml — Types: code128, ean13, ean8, upca, code39, isbn13. Width: 100-2000px, Height: 50-800px.Create a tracked QR code that logs every scan with device, location, and referrer data. Returns a short redirect URL.
{
"target_url": "https://mysite.com/menu",
"label": "Table 5 Menu",
"campaign": "summer-2026"
}curl -X POST https://apresskit.app/v1/qr-track/create \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"target_url": "https://mysite.com/menu", "label": "Table 5"}'
import requests
resp = requests.post(
"https://apresskit.app/v1/qr-track/create",
headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
json={
"target_url": "https://mysite.com/menu",
"label": "Table 5 Menu",
"campaign": "summer-2026",
},
)
data = resp.json()
print(data["redirect_url"]) # https://apresskit.app/q/abc123
const resp = await fetch("https://apresskit.app/v1/qr-track/create", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_JWT_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
target_url: "https://mysite.com/menu",
label: "Table 5 Menu",
}),
});
const data = await resp.json();
console.log(data.redirect_url);
id, short_code, redirect_url, target_url, label, campaign. Auth: JWT token (not API key).List all tracked QR codes for the authenticated user with scan counts and status.
curl https://apresskit.app/v1/qr-track/list \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
import requests
resp = requests.get(
"https://apresskit.app/v1/qr-track/list",
headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
)
for qr in resp.json()["codes"]:
print(f"{qr['label']}: {qr['total_scans']} scans")
const resp = await fetch("https://apresskit.app/v1/qr-track/list", {
headers: { "Authorization": "Bearer YOUR_JWT_TOKEN" },
});
const { codes } = await resp.json();
codes.forEach(qr => console.log(qr.label, qr.total_scans));
id, short_code, redirect_url, target_url, label, campaign, total_scans, is_active, created_at.Get detailed scan analytics for a specific QR code: daily counts, device breakdown, countries, cities, browsers.
curl "https://apresskit.app/v1/qr-track/QR_ID/analytics?days=30" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
import requests
resp = requests.get(
f"https://apresskit.app/v1/qr-track/{qr_id}/analytics",
headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
params={"days": 30},
)
data = resp.json()
print(f"Total: {data['total_scans']}, Unique: {data['unique_scans']}")
const resp = await fetch(
`https://apresskit.app/v1/qr-track/${qrId}/analytics?days=30`,
{ headers: { "Authorization": "Bearer YOUR_JWT_TOKEN" } }
);
const data = await resp.json();
console.log(`Total: ${data.total_scans}`);
total_scans, unique_scans, scans_by_day, top_countries, top_devices, top_browsers, top_cities. Query param: days (default 30).Create a hosted page with a shareable URL. Supports link trees, restaurant menus, promo pages, and custom HTML.
{
"title": "Joe's Coffee Menu",
"template": "menu",
"content": {
"name": "Joe's Coffee",
"subtitle": "Since 2020",
"sections": [
{
"title": "Hot Drinks",
"items": [
{"name": "Espresso", "price": "$3.50", "description": "Double shot"},
{"name": "Latte", "price": "$5.00"}
]
}
]
},
"theme": "dark",
"slug": "joes-menu"
}curl -X POST https://apresskit.app/v1/pages/create \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "My Links",
"template": "links",
"content": {
"name": "My Brand",
"links": [
{"label": "Website", "url": "https://example.com"},
{"label": "Instagram", "url": "https://instagram.com/me"}
]
},
"theme": "dark"
}'
import requests
resp = requests.post(
"https://apresskit.app/v1/pages/create",
headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
json={
"title": "My Links",
"template": "links",
"content": {
"name": "My Brand",
"links": [
{"label": "Website", "url": "https://example.com"},
],
},
"theme": "dark",
},
)
data = resp.json()
print(data["url"]) # https://apresskit.app/p/abc123
const resp = await fetch("https://apresskit.app/v1/pages/create", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_JWT_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "My Links",
template: "links",
content: { name: "My Brand", links: [{ label: "Site", url: "https://example.com" }] },
theme: "dark",
}),
});
const data = await resp.json();
console.log(data.url);
id, slug, url, title, template, theme. Templates: links (bio/link tree), menu (restaurant), promo (event/offer), custom (raw HTML). Themes: dark, light, brand.Privacy by Design
Response Headers
X-aPresskit-Request-Id Unique request identifier for debuggingX-aPresskit-Credits-Remaining API calls remaining this billing periodX-aPresskit-Response-Ms Server-side processing time in millisecondsRate Limits
Burst limit: 10 requests/second per API key
Monthly limits by plan:
Error Codes
401 Invalid or missing API key / JWT token403 Email not verified (for API key creation)404 Resource not found413 Input or output exceeds size limit422 Invalid request body (check required fields)429 Rate limit exceeded (burst or monthly)500 Internal server error
aPresskit API