PDF invoice & receipt generator via REST API — perfect for freelancers and small businesses.
- FastAPI — async web framework
- Jinja2 — HTML templates
- fpdf2 — PDF generation with Cyrillic support (DejaVu Sans)
POST /api/invoice— accepts JSON, returns a PDF fileGET /— web form with live preview and PDF download- Beautiful invoice template: placeholder logo, items table, totals, tax, bank details
- Currencies: RUB (₽) and USD ($)
- Auto-increment invoice numbering (persisted to disk)
# Install dependencies
pip install -r requirements.txt
# Run the server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Open http://localhost:8000 in your browser for the web form.
curl -X POST http://localhost:8000/api/invoice \
-H "Content-Type: application/json" \
-o invoice.pdf \
-d '{
"seller_name": "ООО «Ромашка»",
"seller_address": "г. Москва, ул. Примерная, д. 1",
"seller_inn": "7701234567",
"seller_bank": "ПАО Сбербанк",
"seller_account": "40702810000000012345",
"buyer_name": "ИП Иванов И.И.",
"buyer_address": "г. Санкт-Петербург, пр. Невский, д. 10",
"buyer_inn": "770987654321",
"items": [
{"description": "Разработка веб-сайта", "quantity": 1, "unit_price": 150000, "unit": "шт."},
{"description": "Хостинг", "quantity": 12, "unit_price": 500, "unit": "мес."}
],
"tax_rate": 20,
"currency": "RUB",
"due_date": "2026-05-01",
"notes": "Оплата в течение 10 рабочих дней"
}'curl -X POST http://localhost:8000/api/invoice \
-H "Content-Type: application/json" \
-o invoice_usd.pdf \
-d '{
"seller_name": "Acme Corp",
"seller_address": "123 Main St, New York, NY",
"buyer_name": "John Doe",
"buyer_address": "456 Oak Ave, Los Angeles, CA",
"items": [
{"description": "Web Development", "quantity": 80, "unit_price": 150, "unit": "hrs"},
{"description": "Design Services", "quantity": 1, "unit_price": 5000, "unit": "project"}
],
"tax_rate": 10,
"currency": "USD",
"due_date": "2026-05-15"
}'curl -X POST http://localhost:8000/api/invoice \
-H "Content-Type: application/json" \
-o invoice_min.pdf \
-d '{
"seller_name": "My Company",
"buyer_name": "Client",
"items": [{"description": "Consulting", "quantity": 10, "unit_price": 100}]
}'├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app, routes
│ ├── models.py # Pydantic models
│ ├── pdf.py # PDF generation (fpdf2)
│ ├── templates/
│ │ └── form.html # Web form with live preview
│ └── static/
│ ├── logo.png # Placeholder logo
│ └── fonts/ # DejaVu Sans (Cyrillic)
├── requirements.txt
└── README.md
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| seller_name | string | yes | — | Seller company name |
| seller_address | string | no | "" | Seller address |
| seller_inn | string | no | "" | Seller Tax ID |
| seller_bank | string | no | "" | Seller bank name |
| seller_account | string | no | "" | Seller bank account |
| buyer_name | string | yes | — | Buyer company name |
| buyer_address | string | no | "" | Buyer address |
| buyer_inn | string | no | "" | Buyer Tax ID |
| items | Item[] | yes | — | List of line items |
| items[].description | string | yes | — | Item description |
| items[].quantity | number | no | 1 | Quantity |
| items[].unit_price | number | yes | — | Price per unit |
| items[].unit | string | no | "шт." | Unit of measure |
| tax_rate | number | no | 20 | Tax rate (%) |
| currency | string | no | "RUB" | "RUB" or "USD" |
| due_date | string | no | null | Due date (YYYY-MM-DD) |
| notes | string | no | "" | Additional notes |