Sale
Prints a sale receipt.
Like every command, this one goes to the same address. The command name is in the body, not in the URL.
Request
{
"id": "1",
"method": "send",
"data": {
"command": "Sale",
"payload": {
"saleType": "Sale",
"amount": 12500,
"discountAmount": 0,
"totalAmount": 12500,
"shouldPrintReceipt": true,
"products": [
{
"id": "p_1001",
"name": "Espresso",
"barcode": null,
"units": "шт",
"price": 12500,
"vat": 0.12,
"amount": 1,
"isDecimalUnits": false,
"labels": [],
"psid": "10112001001000000",
"packageCode": 1512472,
"unitCode": null,
"discountAmount": 0,
"commissionTIN": null,
"commissionPINFL": null
}
],
"payments": [{ "paymentType": "Cash", "amount": 12500 }]
}
}
}Response
{ "id": "1", "success": true, "data": { "saleId": 142 } }Save saleId. You need it to refund this receipt later, and there is no way to look it up afterwards.
payload
| Field | Type | Description |
|---|---|---|
saleType | string | "Sale" |
amount | integer | Total before discount, in tiyin |
discountAmount | integer | Discount on the whole receipt, in tiyin. 0 if none. |
totalAmount | integer | amount − discountAmount |
products | array | Receipt lines, see below |
payments | array | Payments, see below |
shouldPrintReceipt | boolean | true — print on paper |
products
| Field | Type | Description |
|---|---|---|
id | string | Any unique line id |
name | string | Name printed on the receipt |
barcode | null | Send null |
units | string | "шт" |
price | integer | Price of one unit, in tiyin |
vat | number | 0.12 for 12%. Not 12. |
amount | number | Quantity |
isDecimalUnits | boolean | true for goods sold by weight |
labels | array | Marking codes, one per unit. [] if the product is not marked. |
psid | string | IKPU, exactly 17 digits, as a string |
packageCode | integer | Package code, a number |
unitCode | null | Send null |
discountAmount | integer | Discount on one unit, in tiyin. 0 if none. |
commissionTIN | null | Send null |
commissionPINFL | null | Send null |
payments
| Field | Type | Description |
|---|---|---|
paymentType | string | "Cash", "Card" or "Cashless" |
amount | integer | Amount in tiyin |
Several payments make a split payment:
"payments": [
{ "paymentType": "Card", "amount": 40000 },
{ "paymentType": "Cash", "amount": 5000 }
]The sums must match
The device rejects the receipt if they do not:
amount = sum of (price × amount) of all products
totalAmount = amount − discountAmount
payments ≥ totalAmountExample: 12500 × 2 + 22500 × 1 = 47500 → amount: 47500, with a 2500 discount → totalAmount: 45000, payments must add up to 45000.
Rules
psid and packageCode are required on every line. Without them the receipt is rejected.
Tobacco and alcohol cannot be sold for cash. If any payment is Cash, no product may have a psid starting with 02401, 02402, 02403 (tobacco) or 02203–02208 (alcohol). Even one tiyin of cash blocks the receipt — use Card or Cashless.
Marked goods need codes. For products that require marking, labels must have one code per unit:
{ "name": "Cigarettes", "amount": 2, "labels": ["<code 1>", "<code 2>"] }Timeout
Sale can take up to 6 minutes, because the device may be talking to the tax service. Set your client timeout to at least 400 seconds.
If it times out, do not send it again — the receipt may already be printed. Send PrintLastReceipt and check first.