Generate account statements from HTML, in one API call
account statement PDF API
Statements are long — a month of transactions can run to many pages. The render engine handles the parts that make multi-page documents painful: the table header repeats on every page, page numbers and running footers come built in, and rows never split mid-line.
No credit card · 25 free credits to start
OVERVIEW
What is the account statement PDF API?
The account statement PDF API is an HTTP endpoint that renders a multi-page statement from HTML in one request. You POST the period’s transactions as JSON to /v1/render and get a print-ready PDF back in about 400ms — the table header repeats on every page, “Page 2 of 7” and footers come built in, and rows never split.
A statement is the longest document most billing systems produce: a month — or a quarter — of transactions, each a row, with a running balance carried from the opening figure to the closing one. The hard part has never been the design; it is everything that goes wrong when a single table runs past one page. The column header has to reappear, the page count has to stay correct, the footer has to keep running, and no transaction row may be sliced in half by a page break.
Generating statements from HTML hands all of that to the renderer. You design the statement once as HTML and CSS with a normal <thead> on the transaction table; because the engine is Chrome-grade, that header automatically repeats at the top of every page, and standard CSS break rules keep each row intact across the boundary. Page numbers and a running footer come from the renderer’s header/footer support, so a twelve-page statement still reads as one continuous document with no pagination math on your side.
The merge engine is loop-free, so you build the transaction rows yourself — date, memo, amount, and a running-balance column if you carry one — join them into one string, and drop them in through a single raw {{{ rowsHtml }}} placeholder. The opening and closing balances are ordinary {{ placeholders }}. POST the period’s data to /v1/render and the full statement comes back in roughly 400 milliseconds, however many pages it spans. Nothing is stored on our side; the bytes are streamed back and discarded. For a denser, chart-led view of the same data, see the report PDF API.
THE PROBLEM
Generating account statements in-house is a two-week project you'll maintain forever
Turning HTML into a clean PDF yourself means running headless Chrome and everything around it. Here's the work you skip.
- Writing pagination math to repeat the column header on every page of a long statement.
- Adding "Page 2 of 7" and a running footer to a multi-page document by hand.
- Keeping a transaction row from being cut in half across a page break.
- Standing up a rendering cluster for a document that is really one big table.
THE SOLUTION
From your data to a finished account statement, in one request
Store your account statements layout once, then POST the values to /v1/render and get print-ready application/pdfbytes back in roughly 400ms. Merge is plain{{ }} /{{{ }}} and dotted keys — no template loops to learn, so repeating rows are rendered to HTML and dropped in through one raw placeholder.
- Repeating table headers. A long transaction table repeats its header row on every page, so a 12-page statement still reads like one document.
- Page numbers & running footers. "Page 2 of 7" and a running footer come from the renderer — no manual pagination.
- Clean page breaks. Standard CSS break rules keep a transaction row intact across a page boundary — never a half-row.
curl https://api.pdfinvoiceapi.com/v1/render \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"template": "tpl_statement",
"data": {
"account": "ACME-4471",
"period": "May 2026",
"openingBalance": "€2,140.00",
"rowsHtml": "<tr><td>02 May</td><td>Invoice INV-1019</td><td>€480.00</td></tr><tr><td>11 May</td><td>Payment received</td><td>-€480.00</td></tr>",
"closingBalance": "€2,140.00"
},
"pdf": { "format": "A4", "margin": "20mm", "printBackground": true }
}' \
-o statement.pdfHOW TO
How to generate account statements from HTML
- 01
Design the statement in HTML
Build the statement as HTML and CSS with a real <thead> on the transaction table, an opening-balance line and a closing-balance line. Mark the dynamic values with {{ placeholders }} and add a running-balance column if you carry one.
- 02
Store it once as a template
Save the layout in the dashboard for a tpl_ id. The repeating header, page numbers and footer are part of the template, so every statement you generate paginates the same way.
- 03
POST the period’s transactions to /v1/render
Render the month’s transactions to HTML rows, join them, and pass them through one raw {{{ rowsHtml }}} placeholder alongside the account and period. Send the template id and data with your API key.
- 04
Stream the multi-page PDF back
The response body is the full statement PDF, however many pages it runs. Email it, archive it, or stream it to the customer — the renderer handled the page breaks, headers and page numbers for you.
WHAT YOU GET
The features that matter for account statements
Repeating table headers
A long transaction table repeats its header row on every page, so a 12-page statement still reads like one document.
Page numbers & running footers
"Page 2 of 7" and a running footer come from the renderer — no manual pagination.
Clean page breaks
Standard CSS break rules keep a transaction row intact across a page boundary — never a half-row.
FAQ
Account statements on PDFInvoiceAPI — common questions
- How do I generate an account statement PDF from HTML?
- Design the statement as HTML/CSS with {{ placeholders }} and a real <thead> on the transaction table, store it once as a template, then POST the template id and a JSON data object to /v1/render. You get application/pdf bytes back in one synchronous call — no SDK and no browser to run yourself.
- Can it handle a multi-page statement with a running balance?
- Yes. A long transaction table flows onto as many pages as it needs, the column header repeats on every page, and rows never split across a break. Carry the running balance as its own column in the rows you build — the renderer paginates it cleanly.
- Do page numbers and footers get added automatically?
- Yes. “Page 2 of 7” and a running header/footer come from the renderer’s page-template support, so you never write pagination math — a twelve-page statement reads as one continuous document.
- How do I render a month of transactions without loops?
- The merge engine is deliberately loop-free. You render the transaction rows to HTML yourself — date, memo, amount — join them into one string, and drop them in through a single raw {{{ rowsHtml }}} placeholder.
- Can I use my own logo, fonts and brand colours?
- Always — the PDF is your own HTML/CSS. Drive the logo and accent colour from data, or save a brand kit and {{brand.logo}} / {{brand.color}} fill in automatically.
- Are my statements stored on your servers?
- No. Each statement is streamed back in the response and discarded — the content is processed transiently and never persisted on our side.
RELATED
Same API, more documents
The render call that makes account statements makes these too — one endpoint for everything your product hands a customer.
Render your first account statement PDF in the next five minutes
One endpoint, real PDFs, 25 free credits to start. No credit card to begin.
Cancel anytime · no long-term contract