Create and format receipt templates using Handlebars and ReceiptLine. Receipt templates define what printed and digital receipts look like.
Copy for LLM
View as Markdown
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
formatCurrencyfor 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.