Skip to content

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']}")