Recipes for invoice templates
Copy-ready BlockTemplate snippets for recurring tasks — from SEPA QR codes to dynamic VAT rows. Drop them into the body.blocks array (or header / footer).

SEPA giro code (QR) for bank transfers
A qrcode block with EPC-069-12 compliant content sourced from the nested seller.bankAccount (iban is required there — and mandatory for ZUGFeRD/XRechnung with SEPA transfer anyway). Customers scan it in their banking app and transfer details are pre-filled.

1{2 "type": "qrcode",3 "condition": "{{seller.bankAccount.iban}}",4 "data": {5 "size": 120,6 "alignment": "right",7 "eccLevel": "M",8 "content": "BCD\n002\n1\nSCT\n{{seller.bankAccount.bic}}\n{{seller.bankAccount.accountHolder}}\n{{seller.bankAccount.iban}}\nEUR{{total}}\n\n{{invoiceNumber}}\n\nRechnung {{invoiceNumber}}"9 }10}Article-number column in the line-items table
An extra column for the article / service number from items[].articleNumber. When the field is empty, the cell simply stays blank.

1{2 "type": "table",3 "data": {4 "dataSource": "{{items}}",5 "columns": [6 { "field": "articleNumber", "header": "Art. No.", "width": "15%" },7 { "field": "description", "header": "Description", "width": "*" },8 { "field": "quantity", "header": "Qty", "width": "10%", "align": "center" },9 { "field": "unitPrice", "header": "Unit", "width": "15%", "align": "right", "format": "currency" },10 { "field": "netAmount", "header": "Net", "width": "15%", "align": "right", "format": "currency" }11 ]12 }13}Logo on the right, company on the left in the header
Two-column header with the sender address on the left and the logo on the right — repeatOnAllPages turns it into a letterhead. The logo is embedded via a static URL or a Base64 data URI.

1{2 "type": "table",3 "data": {4 "dataSource": "{{items}}",5 "columns": [6 { "field": "articleNumber", "header": "Artikel-Nr.", "width": "15%" },7 { "field": "description", "header": "Beschreibung", "width": "*" },8 { "field": "quantity", "header": "Menge", "width": "10%", "align": "center" },9 { "field": "unitPrice", "header": "Einzel", "width": "15%", "align": "right", "format": "currency" },10 { "field": "netAmount", "header": "Netto", "width": "15%", "align": "right", "format": "currency" }11 ]12 }13}Page number in the footer
The runtime placeholders {{pageNumber}} and {{pageCount}} provide the current page and total page count. Combine with repeatOnAllPages.

1{2 "footer": {3 "repeatOnAllPages": true,4 "blocks": [5 { "type": "line", "data": { "thickness": 0.5, "color": { "token": "lineColor" } } },6 { "type": "text", "data": {7 "content": "Page {{pageNumber}} of {{pageCount}} • Invoice {{invoiceNumber}}",8 "fontSize": 8,9 "alignment": "center",10 "color": { "token": "mutedColor" }11 }}12 ]13 }14}Dynamic VAT rows from taxSummary
One summary row per tax rate — no hard-wired 19% logic. Works for mixed invoices with 7%, 19%, reverse charge (AE) or exempt (Z/E).

1{2 "type": "summary",3 "data": {4 "alignment": "right",5 "labelBold": true,6 "headerRows": [7 { "label": "Net total", "value": "{{subtotal}}", "valueFormat": "currency" }8 ],9 "dynamicRows": {10 "dataSource": "{{taxSummary}}",11 "valueField": "taxAmount",12 "valueFormat": "currency",13 "labelTemplate": "VAT {{taxRate}}% ({{taxCategoryCode}})"14 },15 "footerRows": [16 { "label": "Grand total", "value": "{{total}}", "bold": true, "valueFormat": "currency", "separator": true }17 ]18 }19}Payment terms with early-payment discount
Conditional block using paymentTerms.earlyPaymentDiscount (nested). Renders only when discountPercent is set.

1{2 "type": "text",3 "condition": "{{paymentTerms.earlyPaymentDiscount.discountPercent}}",4 "data": {5 "content": "Payable by {{dueDate}}. Pay within {{paymentTerms.earlyPaymentDiscount.days}} days and get a {{paymentTerms.earlyPaymentDiscount.discountPercent}}% early-payment discount.",6 "fontSize": 9,7 "margin": [0, 12, 0, 0]8 }9}Small-business note (§ 19 UStG)
countrySpecific.isKleinunternehmer is a boolean flag for DE invoices. The statutory note is rendered only when the flag is set.

1{2 "type": "text",3 "condition": "{{countrySpecific.isKleinunternehmer}}",4 "data": {5 "content": "Pursuant to § 19 UStG, no VAT is charged (German small-business rule).",6 "italics": true,7 "fontSize": 9,8 "margin": [0, 12, 0, 0]9 }10}B2G: Leitweg-ID in the header
For invoices to public-sector buyers (DE). Leitweg-ID and buyer reference live under countrySpecific. Payload note: countrySpecific requires the discriminator countryCode: "DE", and EN 16931 expects at least one of leitwegId or buyerReference.

1{2 "type": "keyvalue",3 "condition": "{{countrySpecific.leitwegId}}",4 "data": {5 "layout": "horizontal",6 "labelWidth": 120,7 "labelBold": true,8 "items": [9 { "label": "Leitweg-ID", "value": "{{countrySpecific.leitwegId}}" },10 { "label": "Buyer reference", "value": "{{countrySpecific.buyerReference}}", "optionalMode": "anyEmpty" }11 ]12 }13}Missing a recipe?
Drop us a line — we're happy to add frequently requested patterns to the cookbook.
Suggest a recipe →