Validarea conținutului comenzilor
Fiecare comandă trimisă către API-ul e-bon este validată înainte de a ajunge la dispozitiv. Dacă conținutul nu trece validarea, cererea este respinsă cu HTTP 400 și o listă structurată de erori la nivel de câmp — nicio comandă nu este pusă în așteptare, niciun bon fiscal nu este tipărit.
Această pagină documentează regulile, ca să poți construi cereri care trec din prima.
Validează după constantele fiscale din România
Trei seturi fixe de valori sunt aplicate pe comenzile legate de bonuri.
Cote de TVA
Câmpul vatRate de pe fiecare articol trebuie să fie una dintre cotele valabile în România:
| Cotă | Folosire |
|---|---|
0 | Articole scutite |
9 | Cotă redusă (alimente, cărți, medicamente) |
11 | Cotă redusă (HoReCa, cazare) |
21 | Cotă standard |
Orice altă valoare este respinsă cu:
vatRate must be one of: 0, 9, 11, 21
Tipuri de plată
Fiecare intrare din payments[] trebuie să declare un type din acest set:
| Valoare | Sens |
|---|---|
cash | Plată cu numerar |
card | Plată cu cardul |
voucher | Tichet de masă, voucher cadou etc. |
other | Orice alt mijloc de plată acceptat |
Mesaj de respingere:
type must be one of: cash, card, voucher, other
Motive de stornare
La emiterea unui bon de stornare, reason trebuie să fie unul dintre:
| Valoare | Când se folosește |
|---|---|
operator_error | Eroare a casierului pe bonul original |
refund | Clientul a returnat marfa sau a anulat serviciul |
tax_base_reduction | Corecție a bazei de impozitare (de ex. discount ulterior) |
Mesaj de respingere:
reason must be one of: operator_error, refund, tax_base_reduction
Echilibrează articolele cu plățile
Pentru bonurile care includ atât items, cât și payments, totalurile trebuie să coincidă:
sum(items[i].quantity * items[i].price) == sum(payments[i].amount)
Ambele părți sunt rotunjite la 2 zecimale. O diferență de până la ±0,01 RON este tolerată pentru a absorbi rotunjirile de virgulă mobilă — nu este o marjă de discount.
Dacă totalurile nu coincid, cererea este respinsă cu un mesaj de forma:
Payment total (99.99) does not match items total (100.00)
print_receipt. Se aplică și pe print_reversal_receiptatunci când incluzi payments — vezi nota despre asimetrie de mai jos.Aplică regulile per tip de comandă
Comenzile de mai jos transportă conținut care este validat câmp cu câmp. Comenzile care nu apar aici fie nu primesc conținut, fie au forma fixată de schema cererii.
print_receipt
Cel mai pretențios conținut. Combină validarea articolelor, validarea plăților și verificarea de echilibru articole-vs-plăți.
| Câmp | Regulă |
|---|---|
items | Tablou obligatoriu, ne-vid. |
items[i].name | Obligatoriu, șir ne-vid. |
items[i].quantity | Obligatoriu, număr pozitiv (> 0). |
items[i].price | Număr obligatoriu. |
items[i].vatRate | Obligatoriu, trebuie să fie o cotă de TVA din România. |
payments | Tablou obligatoriu, ne-vid. |
payments[i].type | Obligatoriu, trebuie să fie un tip de plată valid. |
payments[i].amount | Obligatoriu, număr pozitiv (> 0). |
| Articole vs plăți | Totalurile trebuie să coincidă în limita de ±0,01 RON. |
void_receipt
| Câmp | Regulă |
|---|---|
receiptId | Obligatoriu, șir ne-vid. |
cash_in / cash_out
Ambele comenzi folosesc același validator.
| Câmp | Regulă |
|---|---|
amount | Obligatoriu, număr pozitiv (> 0). |
description | Opțional; dacă este furnizat, trebuie să fie șir. |
set_datetime
| Câmp | Regulă |
|---|---|
datetime | Opțional; dacă este furnizat, trebuie să fie un șir ISO-8601. |
non_fiscal_receipt
| Câmp | Regulă |
|---|---|
lines | Tablou obligatoriu cu cel puțin o intrare; fiecare element trebuie să fie șir. |
header | Opțional; dacă este furnizat, trebuie să fie șir. |
set_logo
| Câmp | Regulă |
|---|---|
logo | Obligatoriu, șir ne-vid. |
set_vat_rates
| Câmp | Regulă |
|---|---|
rates | Tablou obligatoriu cu cel puțin o intrare. |
rates[i].name | Obligatoriu, șir ne-vid. |
rates[i].percentage | Obligatoriu, număr ne-negativ (>= 0). |
set_header_footer
| Câmp | Regulă |
|---|---|
header | Tablou obligatoriu de șiruri. |
footer | Tablou obligatoriu de șiruri. |
Tablourile vide sunt acceptate.
set_operator
| Câmp | Regulă |
|---|---|
operatorId | Întreg pozitiv obligatoriu (>= 1). |
name | Obligatoriu, șir ne-vid. |
password | Opțional; dacă este furnizat, trebuie să fie șir. |
print_reversal_receipt
| Câmp | Regulă |
|---|---|
uniqueSaleNumber | Obligatoriu, șir ne-vid. |
originalReceiptNumber | Obligatoriu, șir ne-vid. |
originalReceiptDateTime | Obligatoriu, trebuie să fie un șir de dată parsabil ca ISO-8601. |
fiscalMemorySerialNumber | Obligatoriu, șir ne-vid. |
originalZReportNumber | Opțional; dacă este furnizat, trebuie să fie șir. |
reason | Obligatoriu, trebuie să fie un motiv de stornare valid. |
items | Tablou obligatoriu, ne-vid (aceleași reguli per articol ca la print_receipt). |
payments | Opțional. Dacă este furnizat, fiecare intrare urmează aceleași reguli ca la print_receipt, iar verificarea de echilibru se aplică. |
print_receipt vs print_reversal_receipt
- La
print_receipt,paymentseste obligatoriu. - La
print_reversal_receipt,paymentseste opțional — unele stornări (de exemplu, corectarea unei tipăriri greșite care nu a încasat bani) nu au deloc o componentă de plată.
payments este prezent și ne-vid.Interpretează răspunsul de eroare la validare
Când conținutul nu trece validarea, API-ul returnează HTTP 400 cu acest corp:
{
"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 enumeră fiecare câmp care a eșuat, în ordinea verificării. Pentru a localiza eroarea în propria interfață, mapează pe field + code, nu pe textul message — mesajele sunt doar în engleză și pot evolua.
Endpoint-ul dedicat de stornare folosește aceeași formă, dar message-ul de la nivel superior este "Invalid reversal receipt payload" în loc de "Invalid command payload".
Mai departe
- Referință: Tipuri de comenzi — catalogul complet al formelor de conținut per tip de comandă.
- Referință: Coduri de eroare — catalogul complet
ErrorCode, inclusivVALIDATION_ERROR. - API: Comenzi — contractul
POST /api/v1/commands. - API: Dispozitive — endpoint-urile de comandă per dispozitiv, inclusiv ruta de stornare.
- API: Erori — forma de pe fir a fiecărui răspuns de eroare.
Alerte pentru dispozitive
Înțelege cele cinci alerte pe care e-bon le ridică pentru AMEF-urile tale — hârtie pe terminate, capac deschis, memorie fiscală aproape plină, raport Z întârziat și dispozitiv deconectat — unde apar în Portal și cum le citești din API.
Configurare
Această pagină a fost eliminată. Subiectele de configurare pentru utilizatorii Portalului și pentru integratorii API au fost mutate în secțiunile Portal și API.