Generate PDF Invoices with Python and Doppio

Generating professional PDF invoices is one of the most common use cases for document APIs. With Python and Doppio, you can produce branded, consistent invoices from HTML templates without running Puppeteer or headless Chrome yourself. This tutorial shows how to do it with either FastAPI or Django.

Why HTML + API for invoices?

Designing invoices in HTML and CSS gives you full control over layout, typography, and branding. You can reuse the same templates for web preview and PDF export. A dedicated PDF API like Doppio handles rendering and scaling so you don't manage browser processes or memory limits on your server.

1. Create an HTML invoice template

Use a simple HTML template with placeholders for dynamic data. You can render this with Jinja2 (Flask/Django) or pass variables via Doppio's template feature. Example structure:

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Invoice {{ invoice_number }}</title></head>
<body>
  <h1>Invoice #{{ invoice_number }}</h1>
  <p>Date: {{ date }}</p>
  <p>Bill to: {{ customer_name }}</p>
  <table>
    <tr><th>Description</th><th>Amount</th></tr>
    {% for line in lines %}
    <tr><td>{{ line.description }}</td><td>{{ line.amount }}</td></tr>
    {% endfor %}
  </table>
  <p>Total: {{ total }}</p>
</body>
</html>

2. Call the Doppio API from Python

Install requests (or use httpx for async). Send a POST request to Doppio's PDF sync endpoint with your HTML. You can either:

  • Render the HTML in your app (Jinja2, etc.) and send it as base64-encoded content, or
  • Use a Doppio template and pass templateData in the payload.
import base64
import requests

API_KEY = "your-doppio-api-key"
url = "https://api.doppio.sh/v1/render/pdf/sync"

html_content = """
<!DOCTYPE html>
<html><body>
  <h1>Invoice #INV-001</h1>
  <p>Total: $1,234.56</p>
</body></html>
"""

response = requests.post(
    url,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "page": {
            "setContent": {"html": base64.b64encode(html_content.encode("utf-8")).decode("utf-8")},
            "pdf": {"format": "A4", "printBackground": True},
        },
    },
    timeout=60,
)
response.raise_for_status()
result = response.json()
pdf_url = result.get("documentUrl")  # Download the PDF from this URL

3. Integrate with FastAPI or Django

In FastAPI, expose an endpoint that builds the HTML from your template (e.g. with Jinja2), calls Doppio, and returns the PDF or redirects to the document URL. In Django, use a view that renders a template to a string, then POSTs to Doppio and streams the PDF response or saves it to storage.

For high volume, use Doppio's async endpoint and webhooks so your app doesn't block waiting for the PDF. You can also upload the PDF directly to S3 or your storage via Doppio's presigned URL support.

Summary

With Python and Doppio you get scalable, branded PDF invoices from HTML templates, no headless browser to maintain. For more options (margins, headers, footers), see the Doppio documentation and the CSS Paged Media guide for native PDF styling.

Generate PDF Invoices with Python and Doppio