Generate invoice PDFs from HTML templates
Turn an HTML invoice template into a PDF: fill it with your template engine, set the page layout in CSS and POST it to /v1/weasyprint/render.
Last updated
Fill your HTML invoice template with the template engine you already
use, then POST the result to /v1/weasyprint/render. The response is the
invoice PDF.
- Keep one
invoice.htmltemplate in your code (Jinja2, ERB, Handlebars or another engine). - Render it with the invoice data into an HTML string.
- Send the string to
/v1/weasyprint/renderand store or email the PDF.
<style>
@page {
size: A4;
margin: 20mm;
@bottom-center { content: "Page " counter(page) " of " counter(pages); font-size: 9pt; }
}
body { font-family: "DejaVu Sans", sans-serif; font-size: 10pt; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 6px 8px; border-bottom: 1px solid #ddd; text-align: left; }
.num { text-align: right; }
tr { break-inside: avoid; }
</style>
<h1>Invoice 2026-001</h1>
<table>
<thead>
<tr><th>Item</th><th class="num">Qty</th><th class="num">Price</th></tr>
</thead>
<tbody>
<tr><td>Design work</td><td class="num">12 h</td><td class="num">1,200.00 €</td></tr>
</tbody>
</table>
<p><strong>Total: 1,200.00 €</strong></p>
<thead> repeats the column headings on every page of a long table.
break-inside: avoid keeps each row on one page.
Logo and fonts
The logo goes in as a data: URI (how).
Fonts other than DejaVu load with @font-face
(CSS support).
In production
The call returns when the PDF is ready. The time limit covers the whole
render: 20 s with a key, 8 s without. With an API key, an invoice costs 1
credit, whatever its page count. The PDF carries no timestamps, so the same
HTML gives the same file while the engine version stays the same. For an
archive, a paid plan writes PDF/A-2b or PDF/A-3b (pdf_variant).
Next step
Paste your template into the free tool and check the layout.
FAQ
- How do I keep the table headings on every page of a long invoice?
- Put the heading row in a thead element. The renderer repeats it at the top of every page the table spans.
- Can I include a company logo?
- Yes, as a data: URI in the img element. The renderer loads no external URLs, so a remote image URL is rejected with status 400.