Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Receipt Format

Receipts are the primary transaction records produced by POS terminals. Each receipt is stored as a JSON document in the receipt field of the sales model. This page documents the structure of that JSON.

Every receipt has these top-level fields regardless of type.

ValueDescription
SALESStandard sales transaction
CASH_DROPCash drop from the register
CLOSE_DAYEnd-of-day closing
OPEN_DAYStart-of-day opening
PAID_OUTPaid out from the register
RECEIVED_ON_ACCOUNTReceived on account
CASHIER_LOGINCashier login event
CASHIER_LOGOUTCashier logout event
NO_SALENo-sale drawer open
SETTLEMENTEFT settlement
PURCHASE_ORDERPurchase order
DELIVERYStock receiving
WASTAGEStock wastage

This overview assumes that the receipt is a standard sales receipt.

{
"id": "561c9e0c-6ea5-356f-cd84-9adaba192f49",
"type": "SALES",
"void": false,
"timestamp": "2026-02-05T09:53:15.987Z",
"company": "fad11441-f7b6-47f2-bff1-66c52c7bad1a",
"pos": "09d6a809-5a96-40fc-b148-89576bff513a",
"businessDay": "cfcfc579-c02c-4116-8b68-ca446026f916",
"pricingData": "9fa7b9bf-134a-4896-9cc4-5da67b2c3068",
"receiptNumber": 161,
"orderNumber": 4,
"totalSales": 2150
}
FieldTypeDescription
idguidUnique receipt identifier
typeenumReceipt type (see table above)
statusenum?voided or voiding if the receipt has been voided
voidbooleantrue if the receipt is voided
timestampdatetimeTime of the transaction
companyguidCompany the receipt belongs to
posguidPOS terminal that created the receipt
businessDayguid?Business day the receipt belongs to
pricingDataguid?Pricing data used for this receipt
receiptNumberint?Sequential receipt number within the POS
orderNumberint?Order number within the POS and business day
totalSalesamount?Total sales amount in cents
commentstring?Comment entered at the POS
topCommentstring?Top comment printed on the receipt
deliverystring?Delivery method
salesOrderguid?Linked sales order
age_verifiedboolean?Whether customer age was verified
originalReceiptNumberint?Original receipt number for returns

Present on most receipt types. Contains the cashier who processed the transaction.

{
"cashier": {
"id": "5720375c-6f98-4149-a46c-d827631ab95b",
"name": "Myyjä-1",
"cashier_num": 1,
"active": true,
"data": {
"pos_layout": "2d781f99-f932-4861-82ec-d4f623de2ff1"
}
}
}
FieldTypeDescription
idguidCashier identifier
namestringCashier name
cashier_numintCashier number
activebooleanWhether the cashier is active
dataobjectCashier configuration (layout overrides, etc.)

Optional. Present when a customer is attached to the receipt.

FieldTypeDescription
idguidCustomer identifier
namestringCustomer name
numberstring?Customer number
identstring?Customer identifier (business ID, etc.)
identified_bystring?How the customer was identified

The taxes array summarizes tax by tax group for the entire receipt.

{
"taxes": [
{
"taxGuid": "ccb26d59-c76c-4126-a7e9-af9fcd3156a9",
"taxName": "ALV 13.5%",
"taxPercent": 13.5,
"taxAmount": 256,
"taxlessAmount": 1894,
"totalAmount": 2150
}
]
}
FieldTypeDescription
taxGuidguidTax group identifier
taxNamestringTax group name
taxPercentnumberTax percentage
taxAmountamountTax amount in cents
taxlessAmountamountAmount without tax in cents
totalAmountamountTotal amount including tax in cents

These fields are present when the receipt is associated with table service.

FieldTypeDescription
tableguid?Table identifier
seatsnumber?Number of seats
tableSessionguid?Table session identifier
seatnumber?Seat number (for split-by-seat receipts)
tableStatestring?Table state at the time of the receipt
tableOpsarray?Table state change history with timestamps

Present when the receipt was created from another receipt (e.g. split table).

FieldTypeDescription
origin.idstringOriginal receipt ID
origin.receiptNumbernumber?Original receipt number
origin.tableguid?Original table
origin.typeenum?Origin type (e.g. split)

The posActions array lists actions the POS should perform after the receipt is completed (open drawer, print, send to kitchen, etc.).

{
"posActions": [
{
"id": "9df7907c-...",
"name": "OPEN_DRAWER",
"data": 0
},
{
"id": "3bedd2de-...",
"name": "PRINT_RECEIPT",
"data": "CUSTOMER_RECEIPT"
},
{
"id": "a3f1d7dc-...",
"name": "KITCHEN_PRINT",
"data": "KITCHEN_PRINT1"
}
]
}
ActionDescription
OPEN_DRAWEROpen cash drawer
PRINT_RECEIPTPrint receipt (data specifies which template)
EMAIL_RECEIPTEmail receipt to customer
SMS_RECEIPTSMS receipt to customer
KITCHEN_PRINTSend order to kitchen printer

The salesLines array contains all product lines in the receipt. Each line represents one product sold (or voided).

{
"id": "0",
"qty": 1,
"price": 950,
"tax": "ccb26d59-c76c-4126-a7e9-af9fcd3156a9",
"amountTax": 113,
"amountWithoutTax": 837,
"productId": "020003",
"productGuid": "9ab590d0-f322-4574-8234-bbf3781479db",
"productName": "K3. Kebab salaatilla",
"delivery": "TAKE_OUT",
"sentToKitchen": true,
"no_group": true,
"no_discount": false
}
FieldTypeDescription
idstringLine identifier within the receipt
productIdstringProduct number (PLU code)
productGuidguidProduct GUID
productNamestringProduct name
qtynumberQuantity sold
pricenumberUnit price in cents
taxguidTax group identifier
amountTaxamount?Tax amount for this line in cents
amountWithoutTaxamount?Tax-exclusive amount in cents
deliveryenum?TAKE_OUT or EAT_IN
voidedboolean?Line has been voided
commentstring?Line comment
descriptionstring?Line description
seatint?Seat number (table service)
coursestring?Course name (table service)
sentToKitchenboolean?Whether the line was sent to kitchen
priceOverrideboolean?Price was manually overridden
priceKeyedInboolean?Price was keyed in manually
quantityKeyedInboolean?Quantity was keyed in manually
no_groupboolean?Exclude from product grouping
no_discountboolean?Exclude from automatic discounts
pricingguid?Pricing rule used
startTimedatetime?Service start time (timed items)
endTimedatetime?Service end time (timed items)

Products sold as part of a combo meal or with modifiers use the modifiers array and linked item fields. The parent item lists modifier line IDs in modifiers, and each modifier line references back via menuItem.

[
{
"id": "1",
"productName": "B1. MANDO Burger",
"price": 950,
"modifiers": [
"2",
"3"
]
},
{
"id": "2",
"productName": "-TOMAATTI",
"price": 0,
"menuItem": "b1efac6e-a87e-707e-d727-d931b4dd66bf",
"forceModifier": true,
"topLevelPrice": false
},
{
"id": "3",
"productName": "+ LISÄPIHVI",
"price": 250,
"menuItem": "35cd4f0a-ca30-271a-2590-f98b36d4b93c",
"forceModifier": true,
"topLevelPrice": false
}
]
FieldTypeDescription
modifiersstring[]?IDs of modifier/linked sales lines
menuItemguid?Menu item definition that caused this modifier
isLinkedItemboolean?This line is a linked/modifier item
forceModifierboolean?This line is a forced modifier (always added)
topLevelPriceboolean?Modifier price is included in the parent price

Each sales line can have its own discounts array with line-level discounts.

FieldTypeDescription
idstring?Discount identifier
namestring?Discount name
typestring?Discount type
amountamount?Discount amount in cents
originalAmountamount?Original amount before discount
manualboolean?Manually applied discount
qtynumber?Quantity affected
bundlableboolean?Part of a bundle discount
productsPerDiscountint?Products per discount application

Each sales line can have an infocodes array with information collected during the sale.

FieldTypeDescription
idguidInfocode definition identifier
typestringInfocode type
targetstring?Target value
valuestring?Collected value

The optional taxSales array provides a per-tax-group breakdown for a single sales line. This is used when a product contains components taxed at different rates — for example, an Irish Coffee where the alcohol portion is taxed at 25.5% and the non-alcoholic portion at 13.5%.

{
"id": "3",
"qty": 2,
"price": 1500,
"productId": "130002",
"productName": "Irish Coffee",
"tax": "3bbb3660-5b9e-11ef-a550-0800200c9a66",
"amountTax": 433,
"amountWithoutTax": 2567,
"taxSales": [
{
"tax": "ccb26d59-c76c-4126-a7e9-af9fcd3156a9",
"taxAmount": 250,
"totalAmount": 2100,
"taxlessAmount": 1850
},
{
"tax": "3bbb3660-5b9e-11ef-a550-0800200c9a66",
"taxAmount": 183,
"totalAmount": 900,
"taxlessAmount": 717
}
]
}
FieldTypeDescription
taxguidTax group identifier
taxAmountamountTax amount in cents
taxlessAmountamountTax-exclusive amount in cents
totalAmountamountTotal amount including tax in cents

Key observations:

  • tax on the sales line: The line’s primary tax group (25.5% in this case). This is the default tax used for simple products.
  • taxSales array: When present, overrides the simple tax calculation. Each entry represents one tax component of the product.
  • Sum of taxSales: The individual taxAmount values (250 + 183 = 433) sum to the line’s amountTax. Similarly, totalAmount values (2100 + 900 = 3000) sum to qty × price (2 × 1500 = 3000).
  • Receipt-level taxes: The receipt’s top-level taxes array aggregates all tax groups across all lines, including both components of split-VAT products.

Discounts appear in the receipt at two levels: receipt-level in the top-level discounts array, and line-level in each sales line’s discounts array. The discount engine splits products across lines when bundle discounts apply — one line gets the discounted (or free) price, and other lines keep the original price with a reference to the discount.

In a “buy 5 pay for 5, get 6th free” (mix-and-match) scenario, the customer buys 8 items at €3.50 each. The discount engine identifies that 6 items qualify for the bundle: 5 at full price and 1 free. The remaining 2 items are at full price without any discount.

The receipt splits quantities across lines so each line carries its own discount reference. The free item getsprice: 0 with the originalAmount showing its regular price:

{
"salesLines": [
{
"id": "0",
"qty": 1,
"price": 0,
"productId": "1001",
"productName": "Cake, White Chocolate",
"amountTax": 0,
"amountWithoutTax": 0,
"discounts": [
{
"id": "6FOR5",
"name": "Buy 6 Pay 5",
"qty": 1,
"manual": false,
"bundlable": true,
"originalAmount": 350,
"productsPerDiscount": 6
}
]
},
{
"id": "1",
"qty": 1,
"price": 350,
"productId": "1001",
"productName": "Cake, White Chocolate",
"amountTax": 42,
"amountWithoutTax": 308,
"discounts": [
{
"id": "6FOR5",
"qty": 1,
"manual": false,
"bundlable": true,
"originalAmount": 350,
"productsPerDiscount": 6
}
]
},
{
"id": "2",
"qty": 3,
"price": 350,
"productId": "1002",
"productName": "Cake, Milk Chocolate",
"amountTax": 42,
"amountWithoutTax": 308,
"discounts": [
{
"id": "6FOR5",
"qty": 3,
"manual": false,
"bundlable": true,
"originalAmount": 350,
"productsPerDiscount": 6
}
]
},
{
"id": "5",
"qty": 2,
"price": 350,
"productId": "1003",
"productName": "Cake, Pomada",
"amountTax": 42,
"amountWithoutTax": 308,
"discounts": [
{
"id": "6FOR5",
"qty": 1,
"manual": false,
"bundlable": true,
"originalAmount": 350,
"productsPerDiscount": 6
}
]
},
{
"id": "7",
"qty": 1,
"price": 350,
"productId": "1004",
"productName": "Cake, Caramel",
"amountTax": 42,
"amountWithoutTax": 308
}
]
}

Key observations:

  • Line splitting: The original 2x White Chocolate is split into two lines — one free (price: 0) and one at full price. Both carry the discount reference.
  • bundlable: true: Marks lines that participate in the bundle discount calculation.
  • productsPerDiscount: The total number of products required to trigger the discount (6 in this case).
  • originalAmount: The regular unit price before the discount was applied. On the free line this shows what the item would have cost.
  • qty in discount: The number of units on this line that count toward the discount. Note line "id": "5" has qty: 2 on the sales line but only qty: 1 in the discount — one unit participates in the bundle, the other is at regular price.
  • No discount on remaining items: Line "id": "7" has no discounts array — it is outside the bundle.

App Coupon Discounts with Customer Identification

Section titled “App Coupon Discounts with Customer Identification”

When a customer is identified (e.g. via QR code scan from a loyalty app), the receipt includes a customer object and the discount’s infocodes array links the discount back to the external coupon. The manual: true flag indicates the discount was triggered by the customer identification rather than applied automatically.

{
"customer": {
"id": "00a22e55-7cfe-4291-94e6-445b7ab19120",
"name": "Customer identified",
"ident": "6a2c759f-bf8b-4074-b4e1-1164765498cd"
},
"salesLines": [
{
"id": "0",
"qty": 1,
"price": 518,
"productId": "2518",
"productName": "Toast, Aura & Salami",
"amountTax": 62,
"amountWithoutTax": 456,
"discounts": [
{
"id": "_APP_CP_TOAST_26",
"name": "APP Toast -25%",
"qty": 1,
"manual": true,
"bundlable": true,
"originalAmount": 690,
"productsPerDiscount": 1,
"infocodes": [
{
"id": "eaf86284-42d0-46c4-add6-506e650128ac",
"type": "EXTERNAL_DISCOUNT",
"value": "coupon_dabfcd64-acc9-4b18-8bac-ec79d0781275",
"target": "a245b5dc-9066-4a43-8429-bc3dfee54362"
}
]
}
]
}
],
"externalActions": {
"60453285": {
"customerId": "6a2c759f-bf8b-4074-b4e1-1164765498cd",
"discountList": [
{
"discountId": "coupon_dabfcd64-acc9-4b18-8bac-ec79d0781275",
"posDiscountId": "a245b5dc-9066-4a43-8429-bc3dfee54362"
}
]
}
}
}

Key observations:

  • customer.ident: The external customer identifier from the loyalty system, matched via QR code scan.
  • manual: true: The discount was applied through customer identification, not automatically by the pricing engine.
  • originalAmount: The regular price (€6.90) before the 25% discount. The sales line price reflects the discounted price (€5.18).
  • Discount infocodes: Links the discount to its external source. The type: "EXTERNAL_DISCOUNT" indicates it came from an external system, value holds the coupon identifier, and target references the POS discount definition.
  • externalActions: Top-level object that maps external action IDs to customer and discount information, providing the full chain from customer identification to applied discounts.

The top-level discounts array holds receipt-wide discounts (e.g. total percentage discount). It uses the same discount_line structure as line-level discounts. In the bundle and coupon examples above, discounts is empty because the discounts are applied at the line level.


The tenderLines array contains all payment lines in the receipt. A receipt can have multiple tender lines when paid with multiple payment methods.

{
"tenderLines": [
{
"id": "1",
"tenderId": "d45c30d4-e6c6-45b3-95a6-5fe92e41c534",
"tenderGuid": "d45c30d4-e6c6-45b3-95a6-5fe92e41c534",
"tenderName": "KÄTEINEN",
"tenderType": "TENDER",
"qty": 1,
"amount": 2150,
"total": 2150,
"overTender": 0
}
]
}
FieldTypeDescription
idstringLine identifier within the receipt
tenderIdstringTender type identifier
tenderGuidguidTender GUID
tenderNamestringPayment method name
tenderTypeenumTENDER (payment), CHANGE (change given), or VOID (voided tender)
qtynumberQuantity (usually 1)
amountamountPayment amount in cents
totalamountTotal amount in cents
overTenderamountOverpayment amount in cents (change due)
voidedboolean?Tender line has been voided

When the tender is a card or mobile payment, the cardPayment object contains terminal transaction details.

FieldTypeDescription
typeenum?eft, mobilepay, or mobilepay_refund
batchIdstring?Terminal batch identifier
terminalTransIdstring?Terminal transaction identifier
authNumberstring?Authorization number
cardNumberstring?Masked card number
cardNamestring?Card type name (e.g. “Visa”, “Mastercard”)
archiveIdstring?Archive/reference identifier
entryMethodstring?How the card was read (chip, contactless, etc.)
verificationstring?Verification method (PIN, signature, etc.)
customerReceiptstringCustomer copy of the card receipt
controlReceiptstring?Merchant copy of the card receipt
aidstring?EMV Application Identifier
tvrstring?EMV Terminal Verification Results
tsistring?EMV Transaction Status Information
terminalNamestring?Payment terminal name
terminalBatchstring?Current terminal batch number
attributesobject?Additional terminal-specific attributes

Like sales lines, tender lines can have an infocodes array with information collected during payment (e.g. reference number for invoice payments).


A return receipt reverses a previous sale. It uses type: "SALES" with status: "voided", negative quantities on sales lines, and negative amounts on tender lines. The originalReceiptNumber field links the return to the original receipt.

{
"id": "8c551a50-5ab6-ca47-7b48-799bb6f6e5e7",
"type": "SALES",
"void": false,
"status": "voided",
"timestamp": "2026-02-07T10:01:48.975Z",
"receiptNumber": 577,
"originalReceiptNumber": 575,
"totalSales": -1780,
"taxes": [
{
"taxGuid": "ccb26d59-c76c-4126-a7e9-af9fcd3156a9",
"taxName": "ALV 13.5%",
"taxAmount": -212,
"taxPercent": 14,
"totalAmount": -1780,
"taxlessAmount": -1568
}
],
"salesLines": [
{
"id": "0",
"qty": -2,
"price": 890,
"productId": "2227",
"productName": "Filling, Chicken Caesar",
"amountTax": 106,
"amountWithoutTax": 784
},
{
"id": "2",
"qty": -2,
"price": 0,
"productId": "2124",
"productName": "Bagel, Cheese-Oregano",
"amountTax": 0,
"amountWithoutTax": 0
}
],
"tenderLines": [
{
"id": "1",
"qty": 1,
"amount": -1780,
"total": -1780,
"tenderId": "7bec3395-aeea-40a5-940d-027aa96cad17",
"tenderGuid": "7bec3395-aeea-40a5-940d-027aa96cad17",
"tenderName": "Wolt",
"tenderType": "VOID",
"overTender": 0
}
]
}

Key observations:

  • status: "voided": Marks this receipt as a return/refund. Note that void: false — the receipt itself is valid, it is the original receipt that is being voided.
  • originalReceiptNumber: References the receipt being returned (575 in this case).
  • Negative qty: Sales lines have negative quantities (e.g. -2) indicating items being returned.
  • Positive price: Unit prices remain positive — the negative total comes from the negative quantity.
  • Negative totalSales and taxes: The receipt totals and tax amounts are all negative, reversing the original transaction.
  • tenderType: "VOID": The tender line type is VOID instead of TENDER, and the amount is negative, indicating money returned to the customer.
  • Tender is the refund method: The tender name indicates how the refund was processed (in this case back through the original delivery platform).