Create and format receipt templates using Handlebars and ReceiptLine. Receipt templates define what printed and digital receipts look like.
Receipt templates rely on two complementary technologies:
- Handlebars: formats and injects transaction data into your template.
- ReceiptLine: controls visual layout and print formatting. For more information about ReceiptLine, see the official ReceiptLine specification.
Receipt generation runs in two stages:
- Handlebars processes the template and inserts the transaction data.
- ReceiptLine formats the document for final printing.
For a list of JSON data fields available to templates, see Data fields for receipt templates.
Transaction data access
Use the following fields in Handlebars expressions.
Basic transaction fields
{{timestamp}}
: transaction timestamp{{timestamp_formatted}}
: formatted date and time{{order_number}}
: unique transaction reference{{workstation_id}}
: workstation identifier{{sequence_number}}
: sequential number
Customer fields
{{customer.first_name}}
{{customer.last_name}}
{{customer.company}}
{{customer.account_number}}
Location fields
{{location.location_name}}
{{location.address_line_1}}
: first line of the location address{{location.city}}
{{location.state}}
(state or region){{location.telephone_number}}
Line items
Access line items with the
{{#each line_items}}
helper.{{#each line_items}}
{{description}}
{{quantity}}
{{formatCurrency price}}
{{/each}}
Payments and refunds
- Access payment data using the
{{#each payments}}
helper. - Access refund data using the
{{#each refunds}}
helper.
For all available helpers, see Helpers for receipt templates.
ReceiptLine formatting
Use the following ReceiptLine formatting for your receipt templates:
Basic layout characters
|
separates columns.-
creates horizontal rules.=
indicates a paper cut (printer dependent).
Store Name
-----------------
|Item|Qty|Price|
-----------------
Column widths
Define widths with
{width:...}
. Use *
for a flexible column.{width:*,2,10} # dynamic, 2 chars, 10 chars
Item Name | 2 | 10.00
Text formatting markers
^
enlarges text."
emphasizes text._
underlines text.~
forces spaces inside a token.
^Welcome^
"Total:" _10.00_
Common patterns
Header section
^{{location.location_name}}^
{{location.address_line_1}}
{{location.city}},
{{location.state}}
--------------------------------- Order:
{{order_number}}
Date:
{{timestamp_formatted}}
Item list with totals
{width:*,2,10}
{{#each line_items}}
{{description}}
|{{quantity}}|{{formatCurrency price}}
{{/each}}
--------------------------------- {width:*,20} ^Total:|^{{formatCurrency total}}
Payment section
{width:*,20}
{{#each payments}}
{{type}}|{{formatCurrency amount}}
{{/each}}
Best practices
- Start simple. Build a minimal layout and frequently test with sample data.
- Use spacing. Leave blank lines between logical sections and use horizontal rules for separation.
- Manage widths. Use
{width:*}
for flexible columns and fixed widths for numbers. Test long product names. - Format numbers consistently. Use
formatCurrency
for all monetary values and right-align numeric columns. - Handle optional data. Use conditionals for fields that may be missing and provide sensible fallbacks.
- Group related items. Use specialized helpers (for example,
groupByFacet
) to organize items.
Full example
The following example includes store branding, location data, transaction details, line items with modifiers and attributes, payment details (including card metadata), VAT summary, and reprint handling.
{{logo 32 32}}
{align:center}
{{location.description}}
{{location.address_line_1}}{{#if
location.address_line_2
}}\n{{location.address_line_2}}{{/if}}
{{location.city}}
{{location.state}}
{{location.postal_code}}
{{location.telephone_number}}
{{#if reprint}}
{align:center} ^^^*** Reprinted Receipt ***
{{/if}}
{align:left} |Date: |{{timestamp_formatted}}
|Workstation: |{{workstation_id}}
|Cashier: |{{user_id}}
|Transaction #: |{{order_number}}
|VAT ID: |{{tax_id}}
{align:center}
{{barcode order_number}}
{{#each line_items}}
{width:30,12,*; align:left} |{{truncate description 28}}
|
{{formatCurrency extended_price}}|
{{truncate tax_code 3}}
{width:16,20,4; align:right}
{{#if quantity}}{{quantity}}{{else}}1{{/if}}
@
{{formatCurrency price}}
{{#each price_modifiers}}
|
{{description}}
| ({{formatCurrency amount}})|
{{/each}}
{width:16,20,4; align:right}
{{#each attributes}}
|
{{label}}: |
{{value}}|
{{/each}}
{{/each}}
{width:*; align:center} --- {width:20,*; align:left} ^^^Total: | ^^^{{formatCurrency
total
}}
{width:20,*; align:right}
{{#each payments}}
|^{{type}}: |
{{formatCurrency amount}}
{{#if charge_card}}
{{#if charge_card.additional_data}}
{{#if charge_card.additional_data.receiptData}}
{width:16,20; align:right} |Card: |
{{charge_card.additional_data.receiptData.pan}}
|PAN seq: |
{{charge_card.additional_data.receiptData.panSeq}}
|Pref. name: |
{{charge_card.additional_data.receiptData.preferredName}}
|Card type: |
{{charge_card.additional_data.receiptData.cardType}}
|Payment method: |
{{charge_card.additional_data.receiptData.paymentMethod}}
|Payment variant: |
{{charge_card.additional_data.receiptData.paymentMethodVariant}}
|Entry mode: |
{{charge_card.additional_data.receiptData.posEntryMode}}
|AID: |
{{charge_card.additional_data.receiptData.aid}}
|MID: |
{{charge_card.additional_data.receiptData.mid}}
|TID: |
{{charge_card.additional_data.receiptData.tid}}
|PTID: |
{{charge_card.additional_data.receiptData.ptid}}
|Auth. code: |
{{charge_card.additional_data.receiptData.authCode}}
|Response code: |
{{charge_card.authorization_response_code}}
|Tender: |
{{charge_card.additional_data.receiptData.txRef}}
|Reference: |
{{charge_card.additional_data.receiptData.mref}}
|Type: |
{{charge_card.additional_data.receiptData.txtype}}
|^TOTAL: |
{{formatCurrency charge_card.additional_data.receiptData.totalAmount}}
{{/if}}{{else}}
{width:24,20; align:right} |card number: |
{{charge_card.last4}}
|account type: |
{{charge_card.brand}}/{{charge_card.account_type}}
|application name: |
{{charge_card.application_preferred_name}}
|AID: |
{{charge_card.dedicated_file_name}}
|ARC: |
{{authorization_response_code}}
{{/if}}{{/if}}
{{#if gift_card}}
{width:16,20; align:right} |card number: | *{{gift_card.last4}}
|card type: |
{{gift_card.type}}
{{/if}}
{{#if wallet}}
{width:16,20; align:right} method:
{{wallet.method}}
|transaction id: |
{{wallet.transaction_id}}
|merchant id: |
{{wallet.merchant_id}}
|terminal id: |
{{wallet.terminal_id}}
{{/if}}
{{/each}}
{width:*; align:center} ^VAT Summary {width:10,12,12,*} Code | Rate| Net| VAT
{{#each tax_summary}}
{{code}}
|
{{tax_rate}}|
{{formatCurrency total_net}}|
{{formatCurrency total_tax}}
{{/each}}
---
{{#if reprint}}
{width:*; align:center} ^^^*** Reprinted Receipt ***
{{/if}}
{width:*; align:center} ^^Thank you! Come again!
Troubleshooting
Issue | Checks |
---|---|
Misaligned columns | Confirm width declarations, verify separator placement, remove stray spaces. |
Missing data | Verify field names, check helper spelling, ensure blocks close ({{/each}} , {{/if}} ). |
Formatting not applied | Validate ReceiptLine syntax, verify escape sequences, ensure property blocks (for example {width:...} ) are closed. |
If problems persist, reduce the template to a minimal version, validate output, and add complexity back in small steps.