End-to-End Examples¶
Complete workflows showing how to use InvoicePDFs for real-world scenarios.
Stateless: Render a PDF in One Call¶
The simplest integration — send data, get a PDF. No resources are stored.
curl -X POST https://invoicepdfs.com/api/v1/documents/render \
-H "Authorization: Bearer ip_live_..." \
-H "Content-Type: application/json" \
-d '{
"document_type": "invoice",
"data": {
"invoice_number": "INV-2026-001",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"seller": {
"name": "Acme Corp",
"email": "billing@acme.com",
"tax_id": "US-EIN-12-3456789",
"address": {
"line1": "1 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
}
},
"buyer": {
"name": "Jane Smith",
"email": "jane@example.com",
"address": {
"line1": "42 Oak Ave",
"city": "Portland",
"state": "OR",
"postal_code": "97201",
"country": "US"
}
},
"line_items": [
{
"name": "Consulting",
"description": "Strategy workshop — July 2026",
"quantity": "8",
"unit_price": "250.00",
"unit": "hours",
"taxes": [
{ "name": "Sales Tax", "rate": "8.875", "inclusive": false }
]
}
],
"payment": {
"instructions": "Wire transfer to account below",
"bank_account": {
"bank_name": "First National Bank",
"account_number": "1234567890",
"routing_number": "021000021"
}
}
},
"template": { "id": "tpl_modern" },
"output": { "format": "pdf", "delivery": "url", "expires_in": 3600 }
}'
import httpx
client = httpx.Client(
base_url="https://invoicepdfs.com",
headers={"Authorization": "Bearer ip_live_..."},
)
resp = client.post("/api/v1/documents/render", json={
"document_type": "invoice",
"data": {
"invoice_number": "INV-2026-001",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"seller": {
"name": "Acme Corp",
"email": "billing@acme.com",
},
"buyer": {
"name": "Jane Smith",
"email": "jane@example.com",
},
"line_items": [{
"name": "Consulting",
"quantity": "8",
"unit_price": "250.00",
"unit": "hours",
"taxes": [{"name": "Sales Tax", "rate": "8.875"}],
}],
},
"template": {"id": "tpl_modern"},
"output": {"format": "pdf", "delivery": "url"},
})
data = resp.json()["data"]
print(f"PDF: {data['download_url']}")
print(f"Total: {data['calculation']['total']['amount']}")
# Download the PDF
pdf = client.get(data["download_url"])
with open("invoice.pdf", "wb") as f:
f.write(pdf.content)
const response = await fetch(
"https://invoicepdfs.com/api/v1/documents/render",
{
method: "POST",
headers: {
Authorization: "Bearer ip_live_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
document_type: "invoice",
data: {
invoice_number: "INV-2026-001",
issue_date: "2026-07-20",
currency: "USD",
seller: { name: "Acme Corp" },
buyer: { name: "Jane Smith" },
line_items: [
{ name: "Consulting", quantity: "8", unit_price: "250.00" },
],
},
template: { id: "tpl_modern" },
output: { format: "pdf", delivery: "url" },
}),
}
);
const { data } = await response.json();
console.log("Download:", data.download_url);
Managed: Full Invoice Lifecycle¶
Create, finalize, render, and send an invoice with full status tracking.
import httpx
client = httpx.Client(
base_url="https://invoicepdfs.com",
headers={"Authorization": "Bearer ip_live_..."},
)
# Step 1: Set up seller and buyer (one-time)
seller = client.post("/api/v1/business-profiles", json={
"legal_name": "Acme Corp Inc.",
"email": "billing@acme.com",
"address": {
"line1": "1 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US",
},
}).json()["data"]
customer = client.post("/api/v1/customers", json={
"name": "Jane Smith",
"email": "jane@example.com",
}).json()["data"]
# Step 2: Create draft invoice
invoice = client.post("/api/v1/documents", json={
"document_type": "invoice",
"number": "INV-2026-001",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"business_profile_id": seller["id"],
"customer_id": customer["id"],
"line_items": [
{
"name": "Web Development",
"quantity": "40",
"unit_price": "150.00",
"unit": "hours",
"taxes": [{"name": "Sales Tax", "rate": "8.875"}],
}
],
"notes": [
{"type": "note", "content": "Thank you for your business!"}
],
}).json()["data"]
print(f"Created: {invoice['id']} — {invoice['status']}")
print(f"Total: {invoice['totals']['total']['amount']}")
# Step 3: Finalize
client.post(f"/api/v1/documents/{invoice['id']}/finalize")
# Step 4: Render PDF (must exist before sending with attach_pdf)
render = client.post(f"/api/v1/documents/{invoice['id']}/renders", json={
"template_id": "tpl_modern",
"page_size": "LETTER",
}).json()["data"]
print(f"PDF: {render['download_url']}")
# Step 5: Send via email. Note: /send emails the PDF and records a delivery, but
# does NOT change the document's status — call mark-sent to move it to `sent`.
delivery = client.post(f"/api/v1/documents/{invoice['id']}/send", json={
"to": ["jane@example.com"],
"subject": "Invoice INV-2026-001 from Acme Corp",
"message": "Hi Jane, please find your invoice attached.",
"attach_pdf": True,
}).json()["data"]
print(f"Delivery: {delivery['id']} — {delivery['status']}")
# Step 6: Record the invoice as sent
client.post(f"/api/v1/documents/{invoice['id']}/mark-sent")
# Step 7: Mark as paid (when payment received). mark-paid is allowed from
# `finalized` or `sent`.
client.post(f"/api/v1/documents/{invoice['id']}/mark-paid")
Validate Before Creating¶
Preview calculations without creating any resources.
# Check if data is valid
valid = client.post("/api/v1/documents/validate", json={
"document_type": "invoice",
"data": invoice_data,
}).json()
if valid["data"]["valid"]:
# Preview the totals
calc = client.post("/api/v1/documents/calculate", json={
"document_type": "invoice",
"data": invoice_data,
}).json()
totals = calc["data"]["calculation"]
print(f"Subtotal: {totals['subtotal']['amount']}")
print(f"Tax: {totals['tax_total']['amount']}")
print(f"Total: {totals['total']['amount']}")
Upload Logo and Brand an Invoice¶
# Step 1: Upload logo
with open("logo.png", "rb") as f:
logo = client.post(
"/api/v1/files",
files={"file": ("logo.png", f, "image/png")},
).json()["data"]
# Step 2: Use it in a document render
resp = client.post("/api/v1/documents/render", json={
"document_type": "invoice",
"data": {
"invoice_number": "INV-2026-002",
"issue_date": "2026-07-20",
"currency": "USD",
"seller": {"name": "Acme Corp"},
"buyer": {"name": "Jane Smith"},
"line_items": [
{"name": "Service", "quantity": "1", "unit_price": "500.00"}
],
"branding": {
"logo_file_id": logo["id"],
"primary_color": "#1a365d",
"accent_color": "#2b6cb0",
"footer_text": "Thank you for choosing Acme Corp!",
},
},
"template": {"id": "tpl_modern"},
"output": {"format": "pdf", "delivery": "url"},
})
Batch Monthly Invoicing¶
import httpx
from datetime import date, timedelta
client = httpx.Client(
base_url="https://invoicepdfs.com",
headers={"Authorization": "Bearer ip_live_..."},
)
today = date.today()
due = today + timedelta(days=30)
# Your billing data from your system
customers_to_bill = [
{"customer_id": "cus_01A", "email": "alice@example.com", "amount": "499.00", "plan": "Pro"},
{"customer_id": "cus_01B", "email": "bob@example.com", "amount": "99.00", "plan": "Starter"},
{"customer_id": "cus_01C", "email": "carol@example.com", "amount": "999.00", "plan": "Enterprise"},
]
for i, bill in enumerate(customers_to_bill, 1):
# Create
inv = client.post("/api/v1/documents", json={
"document_type": "invoice",
"number": f"INV-{today.strftime('%Y%m')}-{i:03d}",
"issue_date": today.isoformat(),
"due_date": due.isoformat(),
"currency": "USD",
"business_profile_id": "bp_01ABC",
"customer_id": bill["customer_id"],
"line_items": [{
"name": f"{bill['plan']} Plan — {today.strftime('%B %Y')}",
"quantity": "1",
"unit_price": bill["amount"],
}],
}).json()["data"]
# Finalize, render, send, then record as sent
client.post(f"/api/v1/documents/{inv['id']}/finalize")
client.post(f"/api/v1/documents/{inv['id']}/renders", json={"template_id": "tpl_modern"})
client.post(f"/api/v1/documents/{inv['id']}/send", json={
"to": [bill["email"]],
"attach_pdf": True,
})
client.post(f"/api/v1/documents/{inv['id']}/mark-sent")
print(f"Sent {inv['number']} to {bill['email']}")