Generate polished, single-page PDF invoices from a JSON file with one command.
The project uses the rock-solid ReportLab toolkit — no third-party APIs, 100 % offline.
| ✓ | What you get |
|---|---|
| ✅ | 1-page guarantee – designed to fit neatly on A4 or US-Letter. |
| ✅ | Professional layout – dark header band, crisp table grid, tidy typographic hierarchy. |
| ✅ | Full banking block – combined SWIFT instructions with clear “FIELD 56A / 57A / 59 / 70” labels + optional settlement text. |
| ✅ | Logo support – drop logo.png in the root and you’re branded. |
| ✅ | Zero external services – perfect for CI/CD pipelines or air-gapped systems. |
| ✅ | Easily hackable – tweak colours, fonts, margins, or even insert extra tables with a few lines of Python. |
| ✅ | Outputs go to /invoices – keeps your repo root clean. |
| Requirement | Version | Notes |
|---|---|---|
| Python | 3.8 + | Earlier 3.x should work, but 3.8 + is recommended |
| pip | Latest | For dependency install |
| ReportLab | ≥ 4.0.5 | Installed automatically via pip install -r requirements.txt |
requirements.txt
reportlab>=4.0.5
git clone https://github.com/marco-jardim/invoice-pdf-generator.git
cd invoice-pdf-generator
# (optional) create + activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtpython invoice_generator.py # uses example.json
# OR
python invoice_generator.py mydata.json custom_name.pdfOutput: a timestamped PDF inside invoices/ – e.g. invoices/invoice_20250623_141530.pdf.
All content lives in JSON (no code edits required).
"wire_transfer": {
"owner_type": "Company",
"legal_name": "My Company Ltd.",
"cnpj": "38.659.441/0001-72", // or VAT / EIN etc.
"street": "123 Tech St.",
"city": "London",
"state": "ENG",
"zip": "EC2A 4AA",
"country": "United Kingdom",
"bank": {
"intermediary": {
"name": "THE BANK OF NEW YORK MELLON",
"swift": "IRVTUS3N",
"routing": "021000018"
},
"final": {
"name": "BARCLAYS PLC",
"swift": "BARCGB22",
"account_number": "12345678"
},
"beneficiary": {
"name": "MY COMPANY LTD.",
"iban": "GB12 BARC 2004 3002 3456 78"
}
},
/* optional extra notice shown under the table */
"settlement_text": "FX / CASH<br/>Bacen institution code 05218<br/>Location code 5885 (São Paulo)"
}💡 The script produces a single, readable table:
FIELD 56A – Intermediary Bank: THE BANK OF NEW YORK MELLON
SWIFT IRVTUS3N
ABA 021000018
FIELD 57A – Final Bank: BARCLAYS PLC
SWIFT BARCGB22
Acct# 12345678
FIELD 59 – Beneficiary / IBAN: MY COMPANY LTD.
IBAN GB12 BARC 2004 3002 3456 78
FIELD 70 – Reference (CNPJ): 38.659.441/0001-72
| Task | How-to |
|---|---|
| Add / change logo | Place your PNG, set "logo_path": "mylogo.png". |
| Custom colours / fonts | Edit build_styles() in invoice_generator.py. |
| Change margins or paper size | Adjust the SimpleDocTemplate( … ) margins or put "page_size": "letter" in your JSON. |
| Add columns or extra tables | Build more Table objects and append them to story. |
invoice-pdf-generator/
├── invoices/ # generated PDFs (auto-created)
├── invoice_generator.py # main script
├── example.json # sample data file
├── requirements.txt
└── README.md # you’re reading it
pip install -U reportlab| Problem / Symptom | Likely fix |
|---|---|
ModuleNotFoundError: reportlab |
Run pip install -r requirements.txt inside the active venv. |
| Fonts too large, text overruns page | Reduce fontSize & leading in build_styles() or shorten long descriptions. |
| Need multi-page invoices | Remove the “one-page guarantee”: enable allowSplitting=1 on tables or add a PageBreak(). |
No PDF appears in invoices/ |
Check filename arg; ensure script has write permissions. |
import json, invoice_generator
from pathlib import Path
data = json.loads(Path("my_invoice.json").read_text(encoding="utf-8"))
invoice_generator.generate_invoice(data, "invoices/embedded_call.pdf")Use it in a Flask view, a serverless function, or your CI pipeline.
GNUv3 © 2025 Tormenta Labs & contributors PRs / issues welcome — happy invoicing!
{ "invoice_date": "July 4, 2025", "invoice_number": "20250704-042", "client": { "name": "Client Inc.", "extra": "VAT GB123 456 789" }, "contractor": { "name": "My Company Ltd.", "extra": "United Kingdom" }, "services": [ { "description": "Consulting", "amount": 3000.0 } ], "payment_terms": "Please pay within 15 days.", /* optional */ "logo_path": "logo.png", "page_size": "letter", // default = A4 "wire_transfer": { … } // full banking block (see below) }