Create a receipt template

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:

  1. Handlebars: formats and injects transaction data into your template.
  2. ReceiptLine: controls visual layout and print formatting. For more information about ReceiptLine, see the official ReceiptLine specification.

Receipt generation runs in two stages:

  1. Handlebars processes the template and inserts the transaction data.
  2. 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.
Access line itemshandlebars
{{#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).
Basic layout exampletext
Store Name
-----------------
|Item|Qty|Price|
-----------------

Column widths

Define widths with {width:...}. Use * for a flexible column.
Column width declarationtext
{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.
Text formattingtext
^Welcome^
"Total:" _10.00_

Common patterns

Header section

Header patternhandlebars
^{{location.location_name}}^
{{location.address_line_1}}
{{location.city}},
{{location.state}}
--------------------------------- Order:
{{order_number}}
Date:
{{timestamp_formatted}}

Item list with totals

Items with totalshandlebars
{width:*,2,10}
{{#each line_items}}
  {{description}}
  |{{quantity}}|{{formatCurrency price}}
{{/each}}
--------------------------------- {width:*,20} ^Total:|^{{formatCurrency total}}

Payment section

Payment sectionhandlebars
{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.

Full receipt templatehandlebars
{{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

IssueChecks
Misaligned columnsConfirm width declarations, verify separator placement, remove stray spaces.
Missing dataVerify field names, check helper spelling, ensure blocks close ({{/each}}, {{/if}}).
Formatting not appliedValidate 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.