Generate invoice PDFs in Python

The simplest way to generate invoice PDFs in Python is to POST an invoice template and your billing JSON to the Docweave API: requests.post to /api/v1/pdf and write the returned bytes to a file — no headless browser to install or run yourself.

Invoice template example

Any HTML works as a template. Use {{ placeholders }} for the invoice number, customer, line items, subtotal, tax, total, and due date — the values you pass in data:

<article style="font-family: sans-serif;">
  <header style="display:flex; justify-content:space-between;">
    <h1>Invoice {{ number }}</h1>
    <div>Due {{ due_date }}</div>
  </header>

  <p>Billed to: {{ customer }}</p>

  <table style="width:100%; border-collapse:collapse;">
    {{{ line_items }}}
  </table>

  <p style="text-align:right;">Subtotal: {{ subtotal }}</p>
  <p style="text-align:right;">Tax: {{ tax }}</p>
  <p style="text-align:right;"><strong>Total due: {{ total }}</strong></p>
</article>

Generate the invoice PDF with Python

Send the template and data in the request body, then write the raw PDF bytes to disk:

import requests

API_KEY = "dw_live_your_key"

invoice_template = """
<article style="font-family: sans-serif;">
  <header style="display:flex; justify-content:space-between;">
    <h1>Invoice {{ number }}</h1>
    <div>Due {{ due_date }}</div>
  </header>

  <p>Billed to: {{ customer }}</p>

  <table style="width:100%; border-collapse:collapse;">
    {{{ line_items }}}
  </table>

  <p style="text-align:right;">Subtotal: {{ subtotal }}</p>
  <p style="text-align:right;">Tax: {{ tax }}</p>
  <p style="text-align:right;"><strong>Total due: {{ total }}</strong></p>
</article>
"""

line_items_html = "".join(
    f"<tr><td>{item['description']}</td><td style='text-align:right;'>{item['amount']}</td></tr>"
    for item in [
        {"description": "Design services", "amount": "$900.00"},
        {"description": "Hosting (monthly)", "amount": "$140.00"},
    ]
)

response = requests.post(
    "https://docweave.dev/api/v1/pdf",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Accept": "application/pdf",
    },
    json={
        "source": {
            "type": "template",
            "template": invoice_template,
            "data": {
                "number": "INV-042",
                "customer": "Acme Inc.",
                "due_date": "2026-08-01",
                "line_items": line_items_html,
                "subtotal": "$1,040.00",
                "tax": "$83.20",
                "total": "$1,123.20",
            },
        },
        "idempotencyKey": "inv-042",
    },
    timeout=30,
)
response.raise_for_status()

with open("invoice.pdf", "wb") as f:
    f.write(response.content)

print("Wrote invoice.pdf")

…or from a Python AI agent, via MCP

If your agent runs in Python (LangChain, an MCP-native framework, or a custom client), the Docweave MCP server exposes a generate_pdf tool — the same underlying render, no HTTP boilerplate to write. Start it with npx @docweave/mcp:

# From a Python-based AI agent, over MCP — no HTTP plumbing:
generate_pdf({
  "source": {
    "type": "template",
    "template": invoice_template,
    "data": {
      "number": "INV-042",
      "customer": "Acme Inc.",
      "due_date": "2026-08-01",
      "line_items": line_items_html,
      "subtotal": "$1,040.00",
      "tax": "$83.20",
      "total": "$1,123.20"
    }
  },
  "outputPath": "/tmp/invoice-042.pdf"
})

# Any MCP client can call this tool once the server is registered — start it with:
# npx @docweave/mcp

FAQ

What's the simplest way to generate an invoice PDF in Python?

POST an HTML invoice template and a JSON data object to /api/v1/pdf using the requests library, then write response.content to a file. Docweave binds your line items and totals into the {{ placeholders }} and returns the finished PDF — no headless browser to install or manage in your Python environment.

Do I need a PDF library like WeasyPrint or ReportLab installed?

No. Those libraries render the invoice layout locally and require you to manage fonts, CSS support, and a rendering engine yourself. Calling the Docweave API offloads that rendering — your Python code only needs an HTTP client and your invoice template.

Can I reuse the same invoice template for every customer?

Yes. Keep the template string constant and change only the "data" object per request — number, customer, line items, and totals. The layout stays identical across every invoice you generate.

How do I avoid double-billing if my Python script retries a failed request?

Pass an idempotencyKey (for example the invoice number) in the request body. A retry with the same key returns the original PDF instead of rendering — and billing — again. Rendering is billed per document, not per page, so a long itemized invoice costs the same as a short one.

Related

Ready to generate invoice PDFs from Python in production?

Get an API key