Invoice PDF Templates
Invoice PDFs can use a document template selected globally or on a single invoice. The template controls the invoice HTML that is converted to PDF.
Template Selection
PDF generation uses this order:
| Priority | Source | Notes |
|---|---|---|
| 1 | Invoice pdfDocumentId | Explicit template selected on the invoice |
| 2 | documents.invoicePdfDocumentId | Global invoice PDF template setting |
| 3 | cfg_invoice_document_id | Legacy setting kept for existing customers |
| 4 | Default invoice template | Used when no override is selected |
Older invoice templates keep working. A legacy template continues to receive the old field names. A template only receives the v1 field set when the document type is invoice and the schema is:
renderSchema = invoiceDocument
renderSchemaVersion = 1Common Fields
New invoice templates can use these stable fields:
| Field | Type | Included |
|---|---|---|
.schemaVersion | string | invoiceDocument.v1 |
.type | string | sale or purchase |
.invoiceId | number | Invoice ID |
.invoicePrefix | string | Invoice series/prefix |
.invoiceNumber | string | Invoice number |
.invoiceNumber2 | string | Secondary invoice number |
.internalNumber | string | Internal document number |
.customerReference | string | Invoice customer reference snapshot |
.date | date-time | Invoice date |
.currency | string | Currency code, for example EUR |
.totalExclTax | number | Total excluding tax |
.totalTax | number | Tax total |
.totalInclTax | number | Total including tax |
.isInvoicePaid | boolean | Whether the invoice is paid |
.totalDebt | number | Remaining unpaid amount |
.totalPaid | number | Paid amount |
.dueDate | date-time | Payment due date |
.paymentTerm | object | Payment term |
.installments | array | Payment installments, when used |
.comment | string | Invoice comment |
.company | object | Buyer/supplier company details |
.billingAddress | object | Billing address snapshot |
.shippingAddress | object | Shipping address snapshot |
.deliveryContactId | number | Delivery contact reference ID |
.ordererContactId | number | Orderer contact reference ID |
.deliveryContact | object | Delivery contact details, when available |
.ordererContact | object | Orderer contact details, when available |
.related.order | object | Source order details, when the invoice was created from an order |
.order | object | Convenience alias for .related.order |
.lineItems | array | Invoice lines |
.documentCharges | array | Document-level charges |
.settings | object | Invoice settings |
.taxReporting | object | Tax reporting flags |
.customFields | object | Tenant-specific custom fields, when configured |
Legacy aliases such as .docSeries, .document, .invoiceDate, .totalWithVat, .companyInfo, .products, and .lines are still available for compatibility. Prefer the stable fields above for new templates.
Company Fields
Use .company for the buyer/supplier shown on the invoice:
| Field | Type | Included |
|---|---|---|
.company.name | string | Company/person display name |
.company.companyId | number | Company ID |
.company.registrationNumber | string | Company/registration code |
.company.taxNumber | string | VAT/tax code |
.company.isPerson | boolean | True when the record is a person |
.company.address | string | Address line |
.company.postCode | string | Post code |
.company.city | string | City |
.company.country | string | Country name |
.company.countryCode | string | Country code |
.company.phoneNumber | string | Phone number |
Address And Contact Fields
Invoice PDFs should use the invoice snapshot fields, not live address records. Use .billingAddress and .shippingAddress in new templates:
{{ .billingAddress.name }}
{{ .billingAddress.addressLine1 }}
{{ .billingAddress.addressLine2 }}
{{ .billingAddress.city }}
{{ .billingAddress.region }}
{{ .billingAddress.countryName }}
{{ .billingAddress.countryCode }}
{{ .billingAddress.postCode }}
{{ .billingAddress.phone }}
{{ .shippingAddress.name }}
{{ .shippingAddress.addressLine1 }}
{{ .shippingAddress.addressLine2 }}
{{ .shippingAddress.city }}
{{ .shippingAddress.region }}
{{ .shippingAddress.countryName }}
{{ .shippingAddress.countryCode }}
{{ .shippingAddress.postCode }}
{{ .shippingAddress.phone }}Address fields:
| Field | Type | Included |
|---|---|---|
.billingAddress.addressId | number | Billing address reference ID |
.billingAddress.name | string | Billing address display name |
.billingAddress.addressLine1 | string | Billing address line 1 |
.billingAddress.address | string | Compatibility alias for addressLine1 |
.billingAddress.addressLine2 | string | Billing address line 2 |
.billingAddress.city | string | Billing city |
.billingAddress.region | string | Billing region/state/province |
.billingAddress.countryName | string | Billing country name resolved from country code when available |
.billingAddress.countryCode | string | Billing country code |
.billingAddress.postCode | string | Billing post code |
.billingAddress.phone | string | Billing address phone |
.shippingAddress.addressId | number | Shipping address reference ID |
.shippingAddress.name | string | Shipping address display name |
.shippingAddress.addressLine1 | string | Shipping address line 1 |
.shippingAddress.address | string | Compatibility alias for addressLine1 |
.shippingAddress.addressLine2 | string | Shipping address line 2 |
.shippingAddress.city | string | Shipping city |
.shippingAddress.region | string | Shipping region/state/province |
.shippingAddress.countryName | string | Shipping country name resolved from country code when available |
.shippingAddress.countryCode | string | Shipping country code |
.shippingAddress.postCode | string | Shipping post code |
.shippingAddress.phone | string | Shipping address phone |
.invoiceAddress and .deliveryAddress are available only as PDF compatibility aliases for .billingAddress and .shippingAddress. Prefer the new names in all new templates.
Contact references and resolved contact objects:
{{ .deliveryContactId }}
{{ .ordererContactId }}
{{ .deliveryContact.firstName }}
{{ .deliveryContact.lastName }}
{{ .deliveryContact.name }}
{{ .deliveryContact.email }}
{{ .deliveryContact.phone }}
{{ .ordererContact.firstName }}
{{ .ordererContact.lastName }}
{{ .ordererContact.name }}
{{ .ordererContact.email }}
{{ .ordererContact.phone }}Contact fields:
| Field | Type | Included |
|---|---|---|
.deliveryContact.contactId | number | Delivery contact ID |
.deliveryContact.name | string | Delivery contact full name |
.deliveryContact.firstName | string | Delivery contact first name |
.deliveryContact.lastName | string | Delivery contact last name |
.deliveryContact.title | string | Delivery contact title |
.deliveryContact.email | string | Delivery contact email |
.deliveryContact.phone | string | Delivery contact phone |
.deliveryContact.phoneNumber | string | Compatibility alias for phone |
.ordererContact.contactId | number | Orderer contact ID |
.ordererContact.name | string | Orderer contact full name |
.ordererContact.firstName | string | Orderer contact first name |
.ordererContact.lastName | string | Orderer contact last name |
.ordererContact.title | string | Orderer contact title |
.ordererContact.email | string | Orderer contact email |
.ordererContact.phone | string | Orderer contact phone |
.ordererContact.phoneNumber | string | Compatibility alias for phone |
If a contact ID is stored but the contact cannot be resolved, the contact object still contains contactId so templates can guard on it.
Related Order
When an invoice is linked to an order through the order invoiceId, templates can use .related.order. .order is also available as a shorter alias:
{{ with .related.order }}
{{ .documentNumber }}
{{ .orderId }}
{{ .poNumber }}
{{ .customerReference }}
{{ end }}Related order fields:
| Field | Type | Included |
|---|---|---|
.related.order.orderId | number | Source order ID |
.related.order.document | string | Source order document number |
.related.order.documentNumber | string | Stable alias for source order document number |
.related.order.documentType | string | Source order type |
.related.order.type | string | Alias for source order type |
.related.order.date | date-time | Source order date |
.related.order.title | string | Source order title |
.related.order.poNumber | string | Source order PO number |
.related.order.customerReference | string | Source order customer reference |
.related.order.externalOrderId | string | Source external order ID |
.related.order.shippingMethodName | string | Source order shipping method name |
.related.order.shippingMethodSelector | string | Source order shipping method code/selector |
.related.order.trackingNumber | string | Source order tracking number |
.related.order.trackingType | string | Source order tracking carrier/type |
.related.order.carrierCode | string | Source order carrier code |
.related.order.carrierName | string | Source order carrier name |
.related.order.carrierServiceCode | string | Source order carrier service code |
.related.order.carrierServiceName | string | Source order carrier service name |
Line Fields
Invoice lines are available through .lineItems:
{{ range .lineItems }}
{{ .name }} {{ .quantity }} {{ .measurementUnit }}
{{ formatMoney .priceExclTax $.currency 4 }}
{{ formatMoney .totalInclTax $.currency }}
{{ end }}.lineItems[]:
| Field | Type | Included |
|---|---|---|
.lineNo | number | Line number |
.name | string | Product/service name |
.productId | number | Product ID |
.quantity | number | Quantity |
.measurementUnit | string | Measurement unit |
.priceExclTax | number | Unit price excluding tax |
.priceInclTax | number | Unit price including tax |
.isPriceInclTax | boolean | Whether source price includes tax |
.taxPercentage | number | Tax percentage |
.taxCode | string | Tax code |
.taxAmount | number | Fixed tax amount, when used |
.articule | string | Product article/code |
.description | string | Line description |
.lineId | number | Internal line ID |
.discountPerUnit | number | Discount per unit |
.discountPercent | number | Discount percentage |
.totalExclTax | number | Line total excluding tax |
.totalInclTax | number | Line total including tax |
.charges | array | Line-level charges |
.product | object | Product details, when available |
Charge Fields
Document charges are in .documentCharges. Line charges are in .lineItems[].charges.
| Field | Type | Included |
|---|---|---|
.chargeId | number | Applied charge ID |
.chargeTypeId | number | Charge type ID |
.chargeCode | string | Charge code |
.chargeName | string | Charge name |
.calculationType | string | percentage, fixedAmount, or perUnit |
.percentage | number | Percentage value, when used |
.baseAmount | number | Amount used as calculation base |
.chargeAmount | number | Charge amount excluding tax |
.isTaxable | boolean | Whether the charge is taxable |
.taxPercentage | number | Charge tax percentage |
.taxAmount | number | Charge tax amount |
.totalAmount | number | Charge amount including tax |
.currency | string | Currency code |
.remarks | string | Optional remarks |
Use .chargeId for the applied charge ID.
Seller Configuration
Seller/company settings are exposed under .render.configuration.company:
| Field | Included |
|---|---|
.render.configuration.company.name | Seller company name |
.render.configuration.company.registrationCode | Seller registration code |
.render.configuration.company.vatCode | Seller VAT code |
.render.configuration.company.address | Seller address |
.render.configuration.company.city | Seller city |
.render.configuration.company.phone | Seller phone |
.render.configuration.company.email | Seller email |
.render.configuration.company.website | Seller website |
.render.configuration.company.bankDetails | Seller bank details |
.render.configuration.company.logo | Seller logo URL |
Legacy templates can still use .configuration, but new templates should use the .render.configuration fields.
The total amount in words is available as .render.amountInWords. .render.sumInWords is kept only as a compatibility alias.
Render Helpers
The standard template helpers are available:
{{ formatDate .date }}
{{ formatDateLithuanian .date }}
{{ formatDatetimeLithuanian .date }}
{{ formatDateUS .date }}
{{ formatDatetimeUS .date }}
{{ formatDateTimeUS .date }}
{{ formatPrice .totalInclTax }}
{{ formatPrice .priceExclTax 4 }}
{{ formatPrice4 .priceExclTax }}
{{ currencySymbol .currency }}
{{ formatMoney .totalInclTax .currency }}
{{ formatMoney .priceExclTax .currency 4 }}
{{ nl2br .comment }}
{{ T "invoice.total" }}Date helper output formats:
| Helper | Example output |
|---|---|
formatDate | 2026-05-26 |
formatDateLithuanian | 2026-05-26 |
formatDatetimeLithuanian | 2026-05-26 14:30:00 |
formatDateUS | 05/26/2026 |
formatDatetimeUS | 05/26/2026 02:30 PM |
formatDateTimeUS | 05/26/2026 02:30 PM |
formatDate is an alias for formatDateLithuanian. Use formatDateUS when a US-style MM/DD/YYYY date is needed.
Price and currency helpers:
| Helper | Example |
|---|---|
formatPrice .totalInclTax | 12.35 |
formatPrice .priceExclTax 4 | 12.3456 |
formatPrice4 .priceExclTax | 12.3456 |
formatPriceAbs .totalDebt 4 | absolute value with 4 decimals |
formatPriceSubtract .a .b 4 | a - b with 4 decimals |
currencySymbol "USD" | $ |
currencySymbol "EUR" | € |
formatMoney 12.3456 "USD" | $12.35 |
formatMoney 12.3456 "EUR" | 12.35 € |
formatMoney 12.3456 "EUR" 4 | 12.3456 € |
Use formatPrice when the template controls where the currency appears. Use formatMoney when the amount and currency should be rendered together.
Use translation keys through T instead of hard-coded labels when text should be localized.
Versioning
invoiceDocument.v1 is stable. Existing v1 fields will not be renamed or removed without a new schema version. Edited legacy templates are not upgraded automatically; they keep their current fields until a user intentionally changes the schema/version in the document UI.