Liquid objects
An export template reads from two lists. An order template gets orders; a customer template gets customers. Loop over the list and read each entry’s properties with a dot:
{% for order in orders %}{{ order.shippingAddressSnapshot.postcode }}, {{ order.shippingAddressSnapshot.country }}{% endfor %}AB12 3CD, United KingdomThe Preview column on each table below is exactly what Preview Sample writes for that property, and a test in the app checks every row against what an export really contains. A property that does not exist writes nothing and raises no error, so a misspelling shows only as a gap.
Types
| Type | What it is |
|---|---|
| Text | Written as it is. Empty when there is nothing, never null |
| Number | Money, rates and quantities. Compare without quotes: item.qty == 6 |
| True/false | true or false. Use it in an if on its own |
| Object | Has properties of its own: order.shippingAddressSnapshot.city |
| List | Loop over it with for, count it with size, or take one entry by position: order.lineItems.0 |
Numbers are written as the app holds them, not as money. A whole amount keeps one decimal place (168.0, not 168.00). Add | round: 2 to write money with two decimals; see Liquid filters. Rates are decimals: 0.2, not 20.
{% for order in orders %}{{ order.subtotal }} {{ order.grandTotal }} {{ order.lineItems.0.qty }} {{ order.lineItems.0.tax_rate }}{% endfor %}168.0 196.32 6 0.2A position counts from 0. order.lineItems.0 is the first line:
{% for order in orders %}{{ order.lineItems.0.sku }} then {{ order.lineItems.1.sku }}{% endfor %}WH001 then GN002Square brackets (lineItems[0]) are not supported, and a position past the end wraps round to the start rather than writing nothing.
orders
A list of the orders in this export. Each is an order.
order
Every figure is a snapshot taken when the order was placed. A later catalogue or price change never rewrites an order that has been taken.
| Property | Type | Preview | Notes |
|---|---|---|---|
orderId | Text | ORD-0001 | Begins with the Order Prefix set in Business Rules |
exportStatus | Text | Pending | Pending, or Hold - Credit Review for an order over the customer’s credit limit |
customerId | Text | ACC-1042 | The account code, or a NEW- code for a customer created on the tablet |
customerCompanyNameSnapshot | Text | Kestrel Wine Bar | The name as it was when the order was taken |
dateCreated | Text | 2026-08-09 14:32:00 | Always year, month, day, then the time |
requestedDate | Text | 2026-08-16 00:00:00 | The delivery date asked for. Empty if none |
orderTaxCode | Text | T1 | A tax code set for the whole order. Empty if none |
currencyCode | Text | GBP | |
subtotal | Number | 168.0 | The lines before discount and tax |
promotionDiscount | Number | 8.4 | Discount on the whole order |
appliedPromotionCode | Text | SUMMER10 | Empty if no promotion applied |
taxTotal | Number | 32.72 | Tax on the goods and on the delivery charge |
grandTotal | Number | 196.32 | What the customer pays, delivery included |
carriageCode | Text | STD | The delivery method’s code: what your ERP matches on |
carriageTotal | Number | 4.0 | What was charged for delivery, before tax |
carriageMethod | Text | Standard 3-5 days | The delivery method’s name as the customer was quoted it |
carriageQuoted | Number | 6.95 | What the method would have charged, present only when a rep agreed a different charge. Empty otherwise |
carriageWaivedBy | Text | (empty) | The promotion code that made delivery free. Empty otherwise |
repId | Text | USER_3F2A8B1C | The rep who took the order |
repName | Text | Tom Wilson | |
orderNotes | Text | Leave with the cellar door, ask for the duty manager | Delivery instructions. May contain commas and quotes: escape it |
signaturePath | Text | (empty) | Where the signature is stored on the tablet. Your ERP cannot open it |
customDataJson | Text | (empty) | Whatever your own process put there |
poNumber | Text | (empty) | The customer’s PO number from checkout, empty if none was given |
billingAddressSnapshot | Object | An order address | |
shippingAddressSnapshot | Object | An order address: where the order is going | |
lineItems | List | Each entry a line item | |
isLastOrder | True/false | true | True on the last order in the file |
line item
Each entry in order.lineItems. Prices are what this customer was charged, after their price list, any volume break and any sale.
| Property | Type | Preview | Notes |
|---|---|---|---|
sku | Text | WH001 | |
barcode | Text | 5060123400010 | |
title | Text | Glenvalle 12yr Single Malt 70cl | May contain quotes and ampersands: escape it |
brand | Text | Glenvalle | |
mpn | Text | GLV-12-70 | Manufacturer’s part number |
qty | Number | 6 | |
unit_price | Number | 21.0 | Price per unit actually charged, before tax |
price_label | Text | Trade | Which price applied: a price list name, Sale, Volume Tier or Standard |
tax_code | Text | T1 | |
tax_rate | Number | 0.2 | A decimal: 0.2 is 20% |
line_subtotal | Number | 126.0 | unit_price times qty |
line_discount | Number | 6.3 | This line’s share of the order discount |
line_tax | Number | 23.94 | Tax on what the customer actually pays for this line |
line_total | Number | 143.64 | line_subtotal, less line_discount, plus line_tax |
moq | Number | 6 | Minimum order quantity |
order_multiple | Number | 6 | The quantity must be a multiple of this |
primary_image | Text | (empty) | Where the product’s image is stored on the tablet |
isLast | True/false | false | True on the last line of the order |
order address
billingAddressSnapshot and shippingAddressSnapshot on an order. Snapshots: changing a customer’s address later never rewrites an order already taken.
| Property | Type | Preview | Notes |
|---|---|---|---|
name | Text | Kestrel Wine Bar | |
line1 | Text | 1 Sample Street | |
line2 | Text | (empty) | |
city | Text | Anytown | |
county | Text | (empty) | |
postcode | Text | AB12 3CD | |
country | Text | United Kingdom | As it is held on the customer: compare against exactly that |
customers
A list of the customers created or changed on a tablet that your ERP has not yet seen. Each is a customer.
customer
A customer created on a tablet often has properties with nothing in them at all, where Preview’s sample customer has empty text. Both write nothing, but upcase, downcase and capitalize fail on a missing value; put default: "" before them. See Liquid filters.
| Property | Type | Preview | Notes |
|---|---|---|---|
accountId | Text | NEW-3F2A8B1C | Begins NEW- when a rep created the customer offline. Echo it back as OriginalAccountId on your next customer import |
companyName | Text | The Anchor Hotel & Bar, Ltd | Escape it |
contactName | Text | Niamh O'Brien | |
email | Text | orders@anchorhotel.example | |
phone | Text | (empty) | |
mobile | Text | (empty) | |
website | Text | (empty) | |
vatRegistration | Text | IE1234567X | |
eoriNumber | Text | (empty) | |
taxCode | Text | EXPORT | |
priceListId | Text | Trade | |
currencyCode | Text | EUR | |
creditLimit | Number | 5000.0 | |
creditBalance | Number | 1250.0 | The account balance. Used by the shipped templates |
currentBalance | Number | 1250.0 | The same figure under its other name |
accountStatus | Text | Active | |
carriageCode | Text | STD | The customer’s usual delivery method |
internalNotes | Text | Delivery before 11am only | |
billingAddress | Object | An order address’s properties: where the invoice goes | |
shippingAddresses | List | Each entry a customer address | |
isLastCustomer | True/false | true | True on the last customer in the file |
These are in every real export but not in Preview Sample, so Preview writes nothing for them (and join on tags is an error there):
| Property | Type | Notes |
|---|---|---|
tags | List | The customer’s tags, as text. Use join |
assignedUserId | Text | The rep the customer is assigned to |
customDataJson | Text | Whatever your own process put there |
shippingAddressesJson | Text | The delivery addresses as one piece of JSON. Use shippingAddresses instead |
customer address
Each entry in customer.shippingAddresses.
| Property | Type | Preview | Notes |
|---|---|---|---|
name | Text | The Anchor Hotel & Bar, Ltd | |
line1 | Text | 4 Sample Quay | |
line2 | Text | (empty) | |
city | Text | Anytown | |
county | Text | Co. Dublin | |
postcode | Text | A12 B345 | |
country | Text | Ireland | |
isDefault | True/false | true | The address a rep is offered first |
Preview’s sample addresses also carry an isLast, but a real export does not, so a separator written on it never appears in the real file. Use forloop.last:
{% for customer in customers %}{% for address in customer.shippingAddresses %}{{ address.line1 }}{% if address.isDefault %} (default){% endif %}{% unless forloop.last %}; {% endunless %}{% endfor %}{% endfor %}4 Sample Quay (default); Unit 7, Sample Trade Park