Skip to content

80 × 220 mm

Receipts

Thermal POS receipt (80 mm)

A narrow 80 mm point-of-sale receipt for a café and bookshop, printed in black only. Items carry modifiers, the GST included in the total is derived from the lines, and the transaction ID is encoded as a Code 128 barcode.

Custom sizeLocale en-AUHTML + Jinja

Opens Dynamic Document API with this template preloaded in a free workspace.

Template language features

  • Loops
  • Conditionals
  • Macros
  • Filters
  • Barcode
  • Currency formatting
  • Date formatting
  • Number formatting

Filters such as format_currency and qrcode are described in the template language reference.

Variables

Derived from the sample data: 6 top-level fields, 35 paths in total. Send the same shape as data.

PathTypeExample
storeobject
store.namestring"Wattle & Quill"
store.taglinestring"Books · Coffee · Paper goods"
store.addressstring"Shop 3, 41 Jacaranda Arcade ⏎ Paddington QLD 4…"
store.abnstring"12 345 678 901"
store.websitestring"wattleandquill.example.com"
saleobject
sale.transaction_idstring"WQ2-260917-0142"
sale.datetimedate"2026-09-17T08:42:00+10:00"
sale.timezonestring"Australia/Brisbane"
sale.registerstring"Till 2"
sale.served_bystring"Jasmin"
sale.order_typestring"Eat in · Table 6"
sale.currencystring"AUD"
sale.localestring"en-AU"
sale.gst_ratenumber0.1
itemsarray<object> · 7
items[].namestring"Flat white"
items[].variantstring"Regular"
items[].quantitynumber2
items[].unit_pricenumber5.2
items[].modifiersarray<object> · 1
items[].modifiers[].namestring"Oat milk"
items[].modifiers[].pricenumber0.8
items[].amountnumber12
paymentobject
payment.methodstring"EFTPOS"
payment.entry_modestring"Contactless"
payment.cardstring"Debit •••• 4821"
payment.auth_codestring"063914"
loyaltyobject
loyalty.programstring"Coffee card"
loyalty.stampsnumber7
loyalty.card_sizenumber10
footer_linesarray<string> · 2"Books can be exchanged within 14 days with thi…"

Sample data

Fictional records used for previews. Replace them with your own data when you call the API.

data.json
{
  "store": {
    "name": "Wattle & Quill",
    "tagline": "Books · Coffee · Paper goods",
    "address": "Shop 3, 41 Jacaranda Arcade\nPaddington QLD 4064",
    "abn": "12 345 678 901",
    "website": "wattleandquill.example.com"
  },
  "sale": {
    "transaction_id": "WQ2-260917-0142",
    "datetime": "2026-09-17T08:42:00+10:00",
    "timezone": "Australia/Brisbane",
    "register": "Till 2",
    "served_by": "Jasmin",
    "order_type": "Eat in · Table 6",
    "currency": "AUD",
    "locale": "en-AU",
    "gst_rate": 0.1
  },
  "items": [
    {
      "name": "Flat white",
      "variant": "Regular",
      "quantity": 2,
      "unit_price": 5.2,
      "modifiers": [{ "name": "Oat milk", "price": 0.8 }],
      "amount": 12.0
    },
    {
      "name": "Chai latte",
      "variant": "Large",
      "quantity": 1,
      "unit_price": 6.2,
      "modifiers": [
        { "name": "Soy milk", "price": 0.8 },
        { "name": "Extra hot", "price": 0 }
      ],
      "amount": 7.0
    },
    {
      "name": "Banana bread",
      "variant": null,
      "quantity": 1,
      "unit_price": 6.5,
      "modifiers": [
        { "name": "Toasted", "price": 0 },
        { "name": "Whipped butter", "price": 1.0 }
      ],
      "amount": 7.5
    },
    {
      "name": "The Cartographer's Garden",
      "variant": null,
      "quantity": 1,
      "unit_price": 32.99,
      "modifiers": [],
      "amount": 32.99
    },
    {
      "name": "Field Notes on Small Birds",
      "variant": null,
      "quantity": 1,
      "unit_price": 24.95,
      "modifiers": [],
      "amount": 24.95
    },
    {
      "name": "Pressed-flower bookmark",
      "variant": null,
      "quantity": 2,
      "unit_price": 4.5,
      "modifiers": [],
      "amount": 9.0
    },
    {
      "name": "Letterpress greeting card",
      "variant": null,
      "quantity": 1,
      "unit_price": 6.0,
      "modifiers": [],
      "amount": 6.0
    }
  ],
  "payment": {
    "method": "EFTPOS",
    "entry_mode": "Contactless",
    "card": "Debit •••• 4821",
    "auth_code": "063914"
  },
  "loyalty": {
    "program": "Coffee card",
    "stamps": 7,
    "card_size": 10
  },
  "footer_lines": [
    "Books can be exchanged within 14 days with this receipt.",
    "Poetry night: first Thursday of the month, 6.30 pm."
  ]
}

Source

The body markup with Jinja, the stylesheet placed in <head>.

{#- 80 mm point-of-sale receipt. Line amounts include modifiers; the total, item count and the
    GST contained in GST-inclusive prices are derived from the items. Black only, for thermal printers. -#}
{%- set locale = sale.locale | default("en-AU") -%}
{%- set currency = sale.currency -%}
{%- set total = items | sum_by("amount") -%}
{%- set gst = (total * sale.gst_rate / (1 + sale.gst_rate)) | round(2) -%}
{%- set item_count = items | sum_by("quantity") | int -%}

{%- macro figure(value) -%}{{ value | format_number(locale, 2) }}{%- endmacro -%}

<div class="receipt">
  <header class="shop">
    <svg class="logo" viewBox="0 0 48 30" aria-hidden="true">
      <path d="M5 27C13 20 25 8 42 3c-5 9-15 19-29 22z" fill="#000000"/>
      <path d="M8 25.5L37 6.5" stroke="#ffffff" stroke-width="0.9"/>
      <circle cx="35" cy="20" r="2.6" fill="#000000"/>
      <circle cx="40.5" cy="17" r="2.2" fill="#000000"/>
      <circle cx="40" cy="23.5" r="2.4" fill="#000000"/>
      <circle cx="45" cy="21" r="1.8" fill="#000000"/>
    </svg>
    <div class="shop-name">{{ store.name }}</div>
    <div class="shop-tagline">{{ store.tagline }}</div>
    <div class="shop-address">{{ store.address | nl2br }}</div>
    <div>ABN {{ store.abn }}</div>
  </header>

  <h1 class="doc-title">Tax invoice</h1>

  <div class="meta">
    <div class="row">
      <span>{{ sale.datetime | format_date("%d/%m/%Y %H:%M", locale, sale.timezone) }}</span>
      <span>{{ sale.register }}</span>
    </div>
    <div class="row"><span>Receipt</span><span>{{ sale.transaction_id }}</span></div>
    <div class="row"><span>Served by {{ sale.served_by }}</span><span>{{ sale.order_type }}</span></div>
  </div>

  <div class="rule"></div>

  <div class="items">
    {% for item in items %}
    {%- set each = item.unit_price + (item.modifiers | sum_by("price")) -%}
    <div class="item">
      <div class="row">
        <span class="qty">{{ item.quantity }}×</span>
        <span class="name">{{ item.name }}{% if item.variant %} · {{ item.variant }}{% endif %}</span>
        <span class="amt">{{ figure(item.amount) }}</span>
      </div>
      {% for modifier in item.modifiers %}
      <div class="row sub">
        <span class="qty"></span>
        <span class="name">+ {{ modifier.name }}{% if modifier.price %} ({{ figure(modifier.price) }}){% endif %}</span>
        <span class="amt"></span>
      </div>
      {% endfor %}
      {% if item.quantity > 1 %}
      <div class="row sub">
        <span class="qty"></span>
        <span class="name">{{ item.quantity }} @ {{ figure(each) }} each</span>
        <span class="amt"></span>
      </div>
      {% endif %}
    </div>
    {% endfor %}
  </div>

  <div class="rule"></div>

  <div class="totals">
    <div class="row"><span>{{ item_count }} item{{ "s" if item_count != 1 else "" }}</span><span></span></div>
    <div class="row grand"><span>Total</span><span>{{ total | format_currency(currency, locale) }}</span></div>
    <div class="row"><span>Includes GST</span><span>{{ gst | format_currency(currency, locale) }}</span></div>
  </div>

  <div class="rule"></div>

  <div class="payment">
    <div class="row">
      <span>{{ payment.method }}{% if payment.entry_mode %} · {{ payment.entry_mode }}{% endif %}</span>
      <span>{{ total | format_currency(currency, locale) }}</span>
    </div>
    <div class="row sub">
      <span>{{ payment.card }}</span>
      {% if payment.auth_code %}<span>Auth {{ payment.auth_code }}</span>{% endif %}
    </div>
  </div>

  {% if loyalty %}
  {%- set remaining = loyalty.card_size - loyalty.stamps -%}
  <div class="rule"></div>
  <div class="loyalty">
    <div class="loyalty-title">{{ loyalty.program }}</div>
    <div class="stamps">
      {% for i in range(1, loyalty.card_size + 1) %}<span class="stamp{% if i <= loyalty.stamps %} filled{% endif %}"></span>{% endfor %}
    </div>
    <div class="loyalty-note">
      {% if remaining > 0 %}{{ remaining }} more stamp{{ "s" if remaining != 1 else "" }} for a free coffee{% else %}Your next coffee is on us{% endif %}
    </div>
  </div>
  {% endif %}

  <div class="barcode">{{ sale.transaction_id | barcode("code128", alt="Barcode " ~ sale.transaction_id) }}</div>

  <footer class="foot">
    {% for line in footer_lines %}<p>{{ line }}</p>{% endfor %}
    <p class="thanks">Thank you for visiting</p>
    <p>{{ store.website }}</p>
  </footer>
</div>

Render it with the API

After adding the template to your workspace, render it by ID and pass your data. Arrays are shortened here.

curl -X POST https://api-eu.dynamicdocumentapi.com/v1/renders \
  -H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "type": "template",
    "template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C"
  },
  "data": {
    "store": {
      "name": "Wattle & Quill",
      "tagline": "Books · Coffee · Paper goods",
      "address": "Shop 3, 41 Jacaranda Arcade\nPaddington QLD 4064",
      "abn": "12 345 678 901",
      "website": "wattleandquill.example.com"
    },
    "sale": {
      "transaction_id": "WQ2-260917-0142",
      "datetime": "2026-09-17T08:42:00+10:00",
      "timezone": "Australia/Brisbane",
      "register": "Till 2",
      "served_by": "Jasmin",
      "order_type": "Eat in · Table 6",
      "currency": "AUD",
      "locale": "en-AU",
      "gst_rate": 0.1
    },
    "items": [
      {
        "name": "Flat white",
        "variant": "Regular",
        "quantity": 2,
        "unit_price": 5.2,
        "modifiers": [
          {
            "name": "Oat milk",
            "price": 0.8
          }
        ],
        "amount": 12
      },
      {
        "name": "Chai latte",
        "variant": "Large",
        "quantity": 1,
        "unit_price": 6.2,
        "modifiers": [
          {
            "name": "Soy milk",
            "price": 0.8
          },
          {
            "name": "Extra hot",
            "price": 0
          }
        ],
        "amount": 7
      }
    ],
    "payment": {
      "method": "EFTPOS",
      "entry_mode": "Contactless",
      "card": "Debit •••• 4821",
      "auth_code": "063914"
    },
    "loyalty": {
      "program": "Coffee card",
      "stamps": 7,
      "card_size": 10
    },
    "footer_lines": [
      "Books can be exchanged within 14 days with this receipt.",
      "Poetry night: first Thursday of the month, 6.30 pm."
    ]
  },
  "output": {
    "format": "pdf",
    "filename": "receipt-thermal-80mm.pdf"
  }
}'