Command payload validation
Every command you send to the e-bon API is validated before it reaches the device. If the payload fails validation, the request is rejected with HTTP 400 and a structured list of field-level errors — no command is queued, no receipt is printed.
This page documents the rules so you can build payloads that pass on the first try.
Validate against Romanian fiscal constants
Three fixed value sets are enforced on receipt-related commands.
VAT rates
Item-level vatRate must be one of the rates currently valid in Romania:
| Rate | Use |
|---|---|
0 | Exempt items |
9 | Reduced rate (food, books, medicines) |
11 | Reduced rate (HoReCa, accommodation) |
21 | Standard rate |
Any other value is rejected with:
vatRate must be one of: 0, 9, 11, 21
Payment types
Each entry in payments[] must declare a type from this set:
| Value | Meaning |
|---|---|
cash | Cash payment |
card | Card payment |
voucher | Meal voucher, gift voucher, etc. |
other | Any other accepted tender |
Rejection message:
type must be one of: cash, card, voucher, other
Reversal reasons
When issuing a reversal receipt, reason must be one of:
| Value | When to use |
|---|---|
operator_error | Cashier mistake on the original receipt |
refund | Customer returned goods or cancelled service |
tax_base_reduction | Tax base correction (e.g. subsequent discount) |
Rejection message:
reason must be one of: operator_error, refund, tax_base_reduction
Balance items against payments
For receipts that carry both items and payments, the totals must match:
sum(items[i].quantity * items[i].price) == sum(payments[i].amount)
Both sides are rounded to 2 decimals. A drift of up to ±0.01 RON is tolerated to absorb floating-point rounding — it is not a discount allowance.
If the totals don't match, the request is rejected with a message like:
Payment total (99.99) does not match items total (100.00)
print_receipt request. It also applies to print_reversal_receiptwhen you include payments — see the asymmetry note below.Apply per-command-type rules
The following commands carry payloads that are validated field-by-field. Commands not listed here either take no payload or only require their shape to match the request body schema.
print_receipt
The most demanding payload. Combines item validation, payment validation, and the items-vs-payments balance check.
| Field | Rule |
|---|---|
items | Required array, non-empty. |
items[i].name | Required, non-empty string. |
items[i].quantity | Required, positive number (> 0). |
items[i].price | Required number. |
items[i].vatRate | Required, must be a Romanian VAT rate. |
payments | Required array, non-empty. |
payments[i].type | Required, must be a valid payment type. |
payments[i].amount | Required, positive number (> 0). |
| Items vs payments | Totals must match within ±0.01 RON. |
void_receipt
| Field | Rule |
|---|---|
receiptId | Required, non-empty string. |
cash_in / cash_out
Both commands share the same validator.
| Field | Rule |
|---|---|
amount | Required, positive number (> 0). |
description | Optional; if provided, must be a string. |
set_datetime
| Field | Rule |
|---|---|
datetime | Optional; if provided, must be an ISO-8601 string. |
non_fiscal_receipt
| Field | Rule |
|---|---|
lines | Required array with at least one entry; every element must be a string. |
header | Optional; if provided, must be a string. |
set_logo
| Field | Rule |
|---|---|
logo | Required, non-empty string. |
set_vat_rates
| Field | Rule |
|---|---|
rates | Required array with at least one entry. |
rates[i].name | Required, non-empty string. |
rates[i].percentage | Required, non-negative number (>= 0). |
set_header_footer
| Field | Rule |
|---|---|
header | Required array of strings. |
footer | Required array of strings. |
Empty arrays are accepted.
set_operator
| Field | Rule |
|---|---|
operatorId | Required positive integer (>= 1). |
name | Required, non-empty string. |
password | Optional; if provided, must be a string. |
print_reversal_receipt
| Field | Rule |
|---|---|
uniqueSaleNumber | Required, non-empty string. |
originalReceiptNumber | Required, non-empty string. |
originalReceiptDateTime | Required, must be a date string parsable as ISO-8601. |
fiscalMemorySerialNumber | Required, non-empty string. |
originalZReportNumber | Optional; if provided, must be a string. |
reason | Required, must be a valid reversal reason. |
items | Required array, non-empty (same per-item rules as print_receipt). |
payments | Optional. If provided, every entry follows the same rules as print_receipt, and the items-vs-payments balance check applies. |
print_receipt vs print_reversal_receipt
- On
print_receipt,paymentsis required. - On
print_reversal_receipt,paymentsis optional — some reversals (for example, correcting a misprint that never collected money) carry no payment leg at all.
payments is present and non-empty.Handle the validation error response
When a payload fails validation, the API returns HTTP 400 with this body:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid command payload",
"details": [
{ "field": "items[0].vatRate", "message": "vatRate must be one of: 0, 9, 11, 21" },
{ "field": "payments", "message": "Payment total (99.99) does not match items total (100.00)" }
]
}
}
details lists every field that failed, in the order they were checked. To localise the error in your own UI, map on field + code rather than the message text — message strings are English-only and may evolve.
The dedicated reversal endpoint uses the same shape, but its top-level message is "Invalid reversal receipt payload" instead of "Invalid command payload".
Where to next
- Reference: Command types — full payload shape catalogue per command type.
- Reference: Error codes — full
ErrorCodecatalogue includingVALIDATION_ERROR. - API: Commands —
POST /api/v1/commandscontract. - API: Devices — per-device command endpoints, including the reversal route.
- API: Errors — wire shape of every error response.
Device alerts
Understand the five device alerts e-bon raises for your fiscal devices — paper low, cover open, fiscal memory almost full, Z report overdue, and disconnected — where they appear in the Portal, and how to consume them from the API.
Configuration
This page has been removed. Configuration topics for Portal users and API integrators have moved to the Portal and API sections.