DEV Community

Rahul
Rahul

Posted on • Originally published at invoicepdf-app.azurewebsites.net

How to generate an invoice PDF in Python (2 clean ways)

How to generate an invoice PDF (without the usual pain)

If you've tried to generate an invoice or receipt PDF programmatically, you know
the options are all annoying: low-level PDF drawing, HTML-to-PDF via headless
Chromium (heavy, slow, breaks on fonts), or a bloated reporting library. For a
document, that's overkill.

Here are two clean ways — a few lines of Python, or a single API call.

Option A — one API call (no dependencies)

InvoicePDF takes JSON and returns a PDF. From any language:

curl -X POST https://invoicepdf-app.azurewebsites.net/invoice \
  -H "Content-Type: application/json" \
  -d '{"number":"INV-1","currency":"USD","seller_name":"Me LLC",
       "buyer_name":"Acme Corp",
       "items":[{"description":"Consulting","quantity":8,"unit_price":120}],
       "tax_rate_percent":10}' \
  --output invoice.pdf
Enter fullscreen mode Exit fullscreen mode

That's it — application/pdf comes back. Free tier, no signup to try. There's a
live playground at https://invoicepdf-app.azurewebsites.net where you can edit the JSON and see the PDF.

Option B — pure Python with fpdf2

If you'd rather keep it in-process, fpdf2 is pure Python (no system libs):

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", "B", 20)
pdf.cell(0, 12, "INVOICE", ln=True)
pdf.set_font("Helvetica", size=11)
pdf.cell(0, 8, "Consulting  8 x $120.00 = $960.00", ln=True)
pdf.output("invoice.pdf")
Enter fullscreen mode Exit fullscreen mode

The one thing people get wrong: money math

Do not use floats for money. 0.1 + 0.2 != 0.3 in floating point, and on an
invoice that becomes $29.700000001. Store amounts as integer minor units
(cents), do the math in integers, and format at the end. InvoicePDF does this
internally so totals are always exact.

Try it

What would make it genuinely useful in your stack — logos, templates, webhooks?
Feedback welcome.

Top comments (0)