Referință API POSfix
Prezentare generală
Serverul API POSfix rulează local pe dispozitivul POS și expune un API REST pe portul 4567 (HTTP). Acesta permite unui sistem ERP extern să efectueze operațiuni fiscale — vânzări, depunere/retragere numerar, rapoarte Z/X, rapoarte periodice și interogări — direct pe terminalul POS prin rețeaua locală.
URL de bază: http://<ip-dispozitiv>:4567
Pornire rapidă
- Asigurați-vă că dispozitivul POS și ERP-ul sunt în aceeași rețea locală.
- Obțineți adresa IP a dispozitivului din
Setări > Hardwareîn aplicația POS, sau de la endpoint-ul de health. - Obțineți cheia API din panoul de control POSfix cloud.
- Verificați conectivitatea:
GET http://<ip-dispozitiv>:4567/api/health - Începeți să efectuați operațiuni fiscale folosind header-ul
X-API-Key.
Autentificare
Toate endpoint-urile (cu excepția /api/health) necesită header-ul X-API-Key.
X-API-Key: cheia-dvs-api
Cheia API este provizionată prin platforma cloud POSfix și este unică per terminal.
Cheie lipsă → 401 MISSING_API_KEY
Cheie invalidă → 401 INVALID_API_KEY
Formatul răspunsului
Fiecare răspuns urmează acest format:
{
"success": true,
"data": { ... },
"error": null,
"timestamp": "2026-02-16T12:00:00.000Z"
}
În caz de eroare:
{
"success": false,
"error": {
"code": "COD_EROARE",
"message": "Descriere lizibilă",
"details": [ ... ]
},
"timestamp": "2026-02-16T12:00:00.000Z"
}
| Câmp | Tip | Descriere |
|---|---|---|
success | boolean | true dacă operațiunea a reușit |
data | object | null | Datele răspunsului (null în caz de eroare) |
error | object | null | Informații eroare (null în caz de succes) |
error.code | string | Cod de eroare (machine-readable) |
error.message | string | Mesaj de eroare lizibil |
error.details | array | null | Detalii erori de validare (la nivel de câmp) |
timestamp | string | Marcaj temporal ISO 8601 UTC |
Endpoint-uri
1. Stare și Sănătate
GET /api/health
Verifică starea serverului. Nu necesită autentificare.
Returnează versiunea aplicației, starea fiscală, ID-ul terminalului, IP-ul dispozitivului și timpul de funcționare.
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
status | string | Starea serverului: "ready" |
version | string | Versiunea aplicației (ex. "1.0.1+5") |
fiscalStatus | string | Stare fiscală: "online", "offline", "not_fiscal" |
terminalId | string | Identificator terminal |
serverPort | int | Port de ascultare (4567) |
uptime | int | Timp de funcționare server în secunde |
serverStartedAt | string | Marcaj temporal ISO 8601 când serverul a pornit |
deviceIp | string | Adresa IP a dispozitivului în rețeaua locală |
Exemplu răspuns:
{
"success": true,
"data": {
"status": "ready",
"version": "1.0.1+5",
"fiscalStatus": "online",
"terminalId": "T-12345",
"serverPort": 4567,
"uptime": 3600,
"serverStartedAt": "2026-02-16T10:00:00.000Z",
"deviceIp": "192.168.1.50"
},
"error": null,
"timestamp": "2026-02-16T12:00:00.000Z"
}
2. Vânzări
POST /api/sales
Creează o vânzare nouă. Efectuează înregistrarea fiscală la MEV (autoritatea fiscală), printează bonul și opțional livrează bonul prin SMS/email.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
items | array | Da | — | Lista articolelor de vânzare (minim 1) |
items[].id | string | Nu | null | ID extern produs din ERP. Dacă lipsește, payload-ul de sincronizare va conține null |
items[].name | string | Da | — | Denumire produs (1-100 caractere) |
items[].unitPrice | number | Da | — | Preț unitar (trebuie să fie > 0) |
items[].quantity | number | Da | — | Cantitate (trebuie să fie > 0). Zecimale permise dacă allowDecimals: true |
items[].vatCode | string | Da | — | Cod TVA: A, B, C, D, E sau _ |
items[].discountPercent | number | Nu | 0 | Procent reducere la nivel de articol (0-100) |
items[].allowDecimals | boolean | Nu | false | Permite cantități fracționare (ex. 0.750 kg) |
cartDiscount | object | Nu | null | Reducere la nivel de coș |
cartDiscount.percent | number | Da | — | Procent reducere coș (0-100) |
payments | array | Da | — | Lista plăților (minim 1) |
payments[].type | string | Da | — | Cod tip plată ACPS (vezi Tipuri de plată) |
payments[].amount | number | Da | — | Suma plății |
payments[].rrn | string | Nu | null | RRN-ul unei plăți cu cardul deja încasate în altă aplicație sau pe alt terminal, max. 12 caractere. Cu el, casa nu pornește terminalul bancar și doar emite bonul; fără el, încasează ea cardul. Anularea și rambursarea unei plăți cu RRN trimis se fac în aplicația care a încasat cardul. |
amountReceived | number | Da | — | Suma totală primită de la client |
change | number | Da | — | Rest returnat clientului |
delivery | object | Nu | null | Opțiuni de livrare bon (SMS/email) |
delivery.customerPhone | string | Nu | null | Număr telefon pentru livrare SMS (format: +XXXXXXXXXXX) |
delivery.customerEmail | string | Nu | null | Email pentru livrare bon |
delivery.customerName | string | Nu | null | Numele clientului (max 60 caractere) |
delivery.language | string | Nu | "ro" | Limba bonului: "ro", "en", "ru" |
printReceipt | boolean | Nu | true | Printează bonul pe imprimanta POS |
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
saleId | string | UUID local al vânzării |
purchaseId | string | ID achiziție pe server |
serverSaleId | string | ID vânzare pe server |
fiscalOperationId | string | UUID operațiune fiscală |
receiptNumber | int | Număr secvențial bon în cadrul raportului Z curent |
reportNumber | int | Numărul raportului Z curent |
fiscalCode | string | Cod fiscal de la MEV |
mevId | string | null | ID tranzacție MEV (null dacă offline) |
isOffline | boolean | true dacă MEV a fost inaccesibil (bon fiscal offline) |
offlineFiscalCode | string | null | Cod fiscal offline (când operează offline) |
total | number | Total final al vânzării (după reduceri) |
subtotal | number | Subtotal înainte de reducerea pe coș |
amountReceived | number | Suma primită de la client |
change | number | Rest returnat |
vatBreakdown | object | Defalcarea pe coduri TVA (vezi Defalcare TVA) |
paymentBreakdown | array | Lista de obiecte { type, amount } |
qrCodeData | string | URL cod QR pentru verificarea bonului |
mevResponseXml | string | Răspuns XML SOAP de la MEV |
receiptDelivery | object | null | { smsSent, emailSent } — indică faptul că livrarea a fost solicitată, nu confirmată |
createdAt | string | Marcaj temporal ISO 8601 |
Exemplu — Vânzare simplă (1 articol, numerar):
// Cerere
POST /api/sales
{
"items": [
{
"name": "Cafea espresso",
"unitPrice": 45.00,
"quantity": 1,
"vatCode": "B"
}
],
"payments": [
{ "type": "1", "amount": 45.00 }
],
"amountReceived": 45.00,
"change": 0,
"printReceipt": true
}
// Răspuns 200
{
"success": true,
"data": {
"saleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"purchaseId": "server-purchase-001",
"serverSaleId": "server-sale-001",
"fiscalOperationId": "fiscal-op-001",
"receiptNumber": 1,
"reportNumber": 1,
"fiscalCode": "MEV-TXN-001",
"mevId": "MEV-TXN-001",
"isOffline": false,
"offlineFiscalCode": null,
"total": 45.00,
"subtotal": 45.00,
"amountReceived": 45.00,
"change": 0.00,
"vatBreakdown": {
"B": {
"code": "B",
"percent": 20.0,
"vatAmount": 7.50,
"taxableBase": 37.50,
"totalWithVat": 45.00
}
},
"paymentBreakdown": [
{ "type": "1", "amount": 45.00 }
],
"qrCodeData": "https://sift-mev.sfs.md/verify?id=MEV-TXN-001",
"mevResponseXml": "<?xml version=\"1.0\"?><soap:Envelope>...</soap:Envelope>",
"receiptDelivery": null,
"createdAt": "2026-02-16T12:00:00.000Z"
},
"error": null,
"timestamp": "2026-02-16T12:00:00.000Z"
}
Exemplu — Vânzare complexă (articole multiple, plăți mixte, reduceri, livrare):
// Cerere
POST /api/sales
{
"items": [
{
"id": "prod-001",
"name": "Cafea espresso",
"unitPrice": 45.00,
"quantity": 2,
"vatCode": "B"
},
{
"name": "Tort Napoleon (kg)",
"unitPrice": 180.00,
"quantity": 0.750,
"vatCode": "B",
"discountPercent": 10.0,
"allowDecimals": true
},
{
"name": "Apa minerala 0.5L",
"unitPrice": 15.00,
"quantity": 3,
"vatCode": "B"
}
],
"cartDiscount": {
"percent": 5.0
},
"payments": [
{ "type": "1", "amount": 200.00 },
{ "type": "2", "amount": 50.00, "rrn": "123456789012" }
],
"amountReceived": 250.00,
"change": 0,
"delivery": {
"customerPhone": "+37369123456",
"customerEmail": "client@email.com",
"customerName": "Vasile Munteanu",
"language": "ro"
},
"printReceipt": true
}
Erorile de validare returnează HTTP 400 cu detalii la nivel de câmp:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "items[0].name",
"code": "ITEM_NAME_INVALID",
"message": "Item name must be 1-100 characters"
},
{
"field": "items[0].unitPrice",
"code": "ITEM_PRICE_INVALID",
"message": "Unit price must be greater than 0"
}
]
},
"timestamp": "2026-02-16T12:00:00.000Z"
}
GET /api/sales
Listează vânzările cu filtrare pe interval de date și paginare.
Parametri de interogare:
| Parametru | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
dateFrom | string | Nu | — | Data de început (ISO: YYYY-MM-DD) |
dateTo | string | Nu | — | Data de sfârșit (ISO: YYYY-MM-DD) |
limit | int | Nu | 50 | Număr maxim de rezultate pe pagină |
offset | int | Nu | 0 | Offset paginare |
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
sales | array | Lista rezumatelor vânzărilor |
sales[].id | string | UUID vânzare |
sales[].purchaseId | string | ID achiziție server |
sales[].serverSaleId | string | ID vânzare server |
sales[].fiscalOperationId | string | UUID operațiune fiscală |
sales[].cashierId | string | ID casier |
sales[].cashierName | string | Nume casier |
sales[].subtotal | number | Suma subtotal |
sales[].total | number | Suma totală |
sales[].paymentType | string | Eticheta tipului de plată principal |
sales[].paymentAmount | number | Suma plătită |
sales[].changeAmount | number | Rest returnat |
sales[].status | string | Starea sincronizării |
sales[].createdAt | string | Marcaj temporal ISO 8601 |
total | int | Numărul total de vânzări care corespund |
limit | int | Limita aplicată |
offset | int | Offset-ul aplicat |
Exemplu:
GET /api/sales?dateFrom=2026-02-01&dateTo=2026-02-16&limit=50&offset=0
GET /api/sales/{saleId}
Obține detaliile complete ale unei vânzări specifice, inclusiv articolele, plățile și datele operațiunii fiscale.
Parametri de cale:
| Parametru | Tip | Descriere |
|---|---|---|
saleId | string | UUID vânzare |
Răspunsul include:
| Secțiune | Descriere |
|---|---|
items[] | Detalii produs: productId, productName, quantity, unitPrice, originalPrice, discountAmount, markupAmount, netAmount, vatCode, vatPercent, vatAmount |
payments[] | Detalii plată: paymentType, amount, notes |
fiscalOperation | Date fiscale: mevId, receiptNumber, reportNumber, status, isOffline, mevResponseXml, qrCodeData |
Eroare: 404 SALE_NOT_FOUND dacă ID-ul vânzării nu există.
3. Operațiuni cu numerar
POST /api/cash/in
Depune numerar în casă. Creează un bon de serviciu fiscal trimis la MEV.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
amount | number | Da | — | Suma de depus (trebuie să fie > 0) |
reason | string | Nu | null | Motivul depunerii |
printReceipt | boolean | Nu | true | Printează bon de serviciu |
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
operationId | string | UUID operațiune |
fiscalOperationId | string | UUID operațiune fiscală |
receiptNumber | int | Număr bon de serviciu |
reportNumber | int | Numărul raportului Z curent |
mevId | string | null | ID tranzacție MEV |
isOffline | boolean | Dacă operațiunea a fost offline |
amount | number | Suma depusă |
newBalance | number | Noul sold de numerar |
operationType | string | "cashIn" |
mevResponseXml | string | Răspuns XML SOAP |
createdAt | string | Marcaj temporal ISO 8601 |
Exemplu:
// Cerere
POST /api/cash/in
{
"amount": 500.00,
"reason": "Depunere inceput zi",
"printReceipt": true
}
// Răspuns 200
{
"success": true,
"data": {
"operationId": "op-uuid-001",
"fiscalOperationId": "fiscal-op-003",
"receiptNumber": 1,
"reportNumber": 1,
"mevId": "MEV-SVC-001",
"isOffline": false,
"amount": 500.00,
"newBalance": 500.00,
"operationType": "cashIn",
"mevResponseXml": "...",
"createdAt": "2026-02-16T08:00:00.000Z"
}
}
POST /api/cash/out
Retrage numerar din casă. Verifică dacă soldul este suficient înainte de procesare.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
amount | number | Da | — | Suma de retras (trebuie să fie > 0) |
reason | string | Nu | null | Motivul retragerii |
printReceipt | boolean | Nu | true | Printează bon de serviciu |
Câmpuri răspuns: Identice cu depunerea, cu operationType: "cashOut".
Eroare: 409 INSUFFICIENT_CASH_BALANCE dacă soldul curent este mai mic decât suma solicitată.
{
"success": false,
"error": {
"code": "INSUFFICIENT_CASH_BALANCE",
"message": "Cash balance (300.00) is insufficient for withdrawal of 500.00"
}
}
4. Rapoarte
POST /api/reports/z
Generează un Raport Z — închide ziua fiscală.
Aceasta este o operațiune ireversibilă. Resetează contoarele de bonuri și incrementează numărul raportului.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
printReport | boolean | Nu | true | Printează raportul |
Necesită: Terminalul trebuie să fie fiscalizat și să aibă credențiale MEV valide.
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
reportNumber | int | Număr raport Z |
operationId | string | UUID operațiune fiscală |
mevId | string | null | ID tranzacție MEV |
isOffline | boolean | Dacă operațiunea a fost offline |
reportData | object | Datele complete ale raportului (vezi Obiectul Report Data mai jos) |
mevResponseXml | string | Răspuns XML SOAP de la MEV |
generatedAt | string | Marcaj temporal ISO 8601 |
Obiectul Report Data:
| Câmp | Tip | Descriere |
|---|---|---|
reportNumber | int | Număr raport Z |
dailyTotal | number | Total vânzări pe zi |
dailyTax | number | Total TVA pe zi |
dailyUntaxed | number | Suma neimpozitată |
vatBreakdown | object | Defalcare pe coduri TVA |
receiptsIssued | int | Număr de bonuri emise |
lastReceiptNumber | int | Ultimul număr de bon |
receiptsSentToMev | int | Bonuri trimise cu succes la MEV |
paymentTotals | object | Suma per cod tip plată ACPS (ex. { "1": 3000.00, "2": 2000.00 }) |
paymentCounts | object | Număr per cod tip plată ACPS (ex. { "1": 25, "2": 17 }) |
cashIn | number | Total depuneri numerar |
cashOut | number | Total retrageri numerar |
cashBalance | number | Sold numerar curent |
yearTotal | number | null | Total cumulativ anual (doar Z) |
yearTax | number | null | TVA cumulativ anual (doar Z) |
totalSales | number | Total brut vânzări |
totalReturns | number | Total retururi |
returnsCount | int | Număr operațiuni de retur |
cashInCount | int | Număr operațiuni depunere |
cashOutCount | int | Număr operațiuni retragere |
generatedAt | string | Marcaj temporal ISO 8601 |
POST /api/reports/x
Generează un Raport X — instantaneu intermediar al zilei fiscale.
NU resetează niciun contor. Aceeași structură de cerere/răspuns ca și Raportul Z.
POST /api/reports/periodic
Generează un Raport Periodic — date agregate din mai multe rapoarte Z.
Acesta este doar un raport local (nu se trimite la MEV). Suportă două moduri de filtrare mutual exclusive.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
dateFrom | string | Condiționat | — | Data de început (ISO: YYYY-MM-DD). Obligatoriu pentru modul interval de date |
dateTo | string | Condiționat | — | Data de sfârșit (ISO: YYYY-MM-DD). Obligatoriu pentru modul interval de date |
reportFrom | int | Condiționat | — | Numărul raportului Z de început. Pentru modul interval de rapoarte |
reportTo | int | Condiționat | — | Numărul raportului Z de sfârșit. Pentru modul interval de rapoarte |
detailed | boolean | Nu | false | Include defalcarea individuală pe rapoarte Z |
printReport | boolean | Nu | true | Printează raportul pe imprimanta POS |
Moduri de filtrare (mutual exclusive — furnizați un singur set):
- Interval de date:
dateFrom+dateTo - Interval de numere rapoarte:
reportFromși/saureportTo(ambele opționale — omitețireportFrompentru a începe de la Z#1, omitețireportTopentru ultimul)
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
filterMode | string | "dateRange" sau "reportRange" |
dateFrom | string | Data de început (YYYY-MM-DD) |
dateTo | string | Data de sfârșit (YYYY-MM-DD) |
reportFrom | int | (doar interval rapoarte) Numărul raportului Z de început |
reportTo | int | (doar interval rapoarte) Numărul raportului Z de sfârșit |
totalSales | number | Total vânzări agregate |
totalTax | number | Total TVA agregat |
totalUntaxed | number | Total neimpozitat agregat |
vatBreakdown | object | Defalcare agregată pe coduri TVA |
receiptsCount | int | Total bonuri din toate rapoartele Z |
paymentTotals | object | Totaluri agregate plăți pe tip |
cashIn | number | Total depuneri numerar |
cashOut | number | Total retrageri numerar |
cashInCount | int | Număr operațiuni depunere |
cashOutCount | int | Număr operațiuni retragere |
zReportsCount | int | Număr rapoarte Z în interval |
xReportsCount | int | Număr rapoarte X în interval |
firstZReportNumber | int | Primul număr raport Z din interval |
lastZReportNumber | int | Ultimul număr raport Z din interval |
firstZReportTimestamp | string | Marcaj temporal închidere primul raport Z |
lastZReportTimestamp | string | Marcaj temporal închidere ultimul raport Z |
totalReturns | number | Retururi agregate |
returnsCount | int | Număr operațiuni de retur |
individualZReports | array | null | Defalcare pe fiecare Z (când detailed: true) |
generatedAt | string | Marcaj temporal ISO 8601 |
Câmpuri raport Z individual (când detailed: true):
| Câmp | Tip | Descriere |
|---|---|---|
reportNumber | int | Număr raport Z |
closedAt | string | Marcaj temporal ISO 8601 când Z-ul a fost închis |
firstReceiptNumber | int | Primul număr de bon din acest Z |
lastReceiptNumber | int | Ultimul număr de bon din acest Z |
receiptsCount | int | Număr de bonuri |
totalSales | number | Total vânzări pentru acest Z |
totalTax | number | Total TVA pentru acest Z |
vatBreakdown | object | Defalcare TVA pentru acest Z |
paymentTotals | object | Totaluri plăți pe tip |
cashIn | number | Depuneri numerar în acest Z |
cashOut | number | Retrageri numerar din acest Z |
Exemplu — Sumar pe interval de date:
// Cerere
POST /api/reports/periodic
{
"dateFrom": "2026-02-01",
"dateTo": "2026-02-16",
"detailed": false,
"printReport": true
}
Exemplu — Sumar pe interval de numere rapoarte Z:
// Cerere
POST /api/reports/periodic
{
"reportFrom": 5,
"reportTo": 10,
"detailed": false,
"printReport": true
}
Exemplu — Detaliat pe interval de date:
// Cerere
POST /api/reports/periodic
{
"dateFrom": "2026-02-01",
"dateTo": "2026-02-16",
"detailed": true,
"printReport": false
}
Erori de validare:
| Cod | Condiție |
|---|---|
FILTER_REQUIRED | Nici interval de date, nici interval de rapoarte nu a fost furnizat |
DATE_RANGE_INVALID | dateFrom este după dateTo |
DATE_TO_FUTURE | dateTo este în viitor |
REPORT_NUMBER_INVALID | reportFrom sau reportTo < 1 |
REPORT_RANGE_INVALID | reportFrom > reportTo |
5. Interogări fiscale
GET /api/fiscal/operations
Interogarea operațiunilor fiscale din baza de date de audit cu filtrare.
Parametri de interogare:
| Parametru | Tip | Obligatoriu | Descriere |
|---|---|---|---|
dateFrom | string | Nu | Data de început (ISO: YYYY-MM-DD) |
dateTo | string | Nu | Data de sfârșit (ISO: YYYY-MM-DD) |
type | string | Nu | Filtru tip operațiune (vezi Tabele de referință) |
status | string | Nu | Filtru stare operațiune (vezi Tabele de referință) |
limit | int | Nu | Număr maxim rezultate (implicit 50) |
offset | int | Nu | Offset paginare (implicit 0) |
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
operations | array | Lista operațiunilor fiscale |
operations[].id | string | UUID operațiune |
operations[].operationType | string | Tipul operațiunii fiscale |
operations[].receiptNumber | int | Număr bon |
operations[].reportNumber | int | Număr raport Z |
operations[].mevId | string | null | ID tranzacție MEV |
operations[].status | string | Starea operațiunii |
operations[].isOffline | boolean | Dacă a operat offline |
operations[].totalAmount | number | Suma operațiunii |
operations[].vatBreakdown | object | Defalcare TVA simplificată |
operations[].vatDetails | object | TVA detaliat cu procent, rată, cost, brut |
operations[].paymentsBreakdown | object | Plăți pe tip |
operations[].mevResponseXml | string | Răspuns XML SOAP |
operations[].errorMessage | string | null | Mesaj de eroare dacă operațiunea a eșuat |
operations[].createdAt | string | Marcaj temporal ISO 8601 creare |
operations[].completedAt | string | Marcaj temporal ISO 8601 finalizare |
total | int | Total operațiuni care corespund |
limit | int | Limita aplicată |
offset | int | Offset-ul aplicat |
GET /api/fiscal/daily-summary
Obține rezumatul zilei fiscale curente. Returnează aceleași date ca un Raport X, dar fără a trimite nimic la MEV. Doar citire, nu necesită blocare fiscală.
Necesită: Terminalul trebuie să fie fiscalizat.
Răspuns: Identic cu obiectul Report Data (vezi secțiunea Raport Z).
6. Printare
POST /api/print
Printează text non-fiscal pe imprimanta termică POS. Suportă layout-uri multi-coloană.
Corpul cererii:
| Câmp | Tip | Obligatoriu | Implicit | Descriere |
|---|---|---|---|---|
lines | array | Da | — | Lista de array-uri de linii |
feedLines | int | Nu | 3 | Număr de linii goale după conținut |
cut | boolean | Nu | true | Taie hârtia după printare |
Formatul liniei — fiecare linie este un array de 1-3 șiruri:
| Coloane | Layout |
|---|---|
["text"] | Lățime completă, aliniat la stânga |
["stânga", "dreapta"] | Aliniat stânga + dreapta |
["stânga", "centru", "dreapta"] | Layout pe trei coloane |
[""] | Linie goală (spațiu) |
Aceasta este o operațiune non-fiscală — fără interacțiune MEV, fără bon fiscal.
Câmpuri răspuns:
| Câmp | Tip | Descriere |
|---|---|---|
linesCount | int | Număr de linii printate |
printedAt | string | Marcaj temporal ISO 8601 |
Exemplu — Raport de inventar (3 coloane):
POST /api/print
{
"lines": [
["RAPORT INVENTAR"],
["Data:", "16.02.2026"],
[""],
["Cod", "Denumire", "Cantitate"],
["────────────────────────────────"],
["001", "Cafea espresso", "150 buc"],
["002", "Tort Napoleon", "12.5 kg"],
["003", "Apa minerala 0.5L", "340 buc"],
[""],
["Total pozitii:", "4"],
["────────────────────────────────"],
["Responsabil:", "", "Ion Popescu"]
],
"feedLines": 3,
"cut": true
}
Eroare: 503 PRINTER_UNAVAILABLE dacă imprimanta este deconectată sau indisponibilă.
Tabele de referință
Coduri de eroare
| Cod | Status HTTP | Descriere |
|---|---|---|
MISSING_API_KEY | 401 | Header-ul X-API-Key nu a fost furnizat |
INVALID_API_KEY | 401 | Cheia API furnizată nu este validă |
VALIDATION_ERROR | 400 | Validarea corpului cererii a eșuat (vezi details[]) |
INVALID_JSON | 400 | Corpul cererii nu este JSON valid |
TERMINAL_NOT_FISCAL | 409 | Terminalul nu este fiscalizat (fără certificat MEV) |
MEV_CREDENTIALS_MISSING | 409 | Terminalul este fiscalizat dar credențialele MEV lipsesc |
FISCAL_DAY_EXPIRED | 409 | Au trecut 24h de la primul bon al zilei fiscale — Raport Z necesar înainte de a continua |
INSUFFICIENT_CASH_BALANCE | 409 | Sold numerar insuficient pentru retragerea solicitată |
MEV_ERROR | 502 | Comunicarea cu MEV (SFS) a eșuat (timeout, eroare SOAP, certificat expirat) |
BUSY | 429 | O altă operațiune fiscală este în curs (timeout 30s depășit) |
SALE_NOT_FOUND | 404 | Vânzarea cu ID-ul specificat nu a fost găsită |
PRINTER_UNAVAILABLE | 503 | Imprimanta nu este disponibilă sau este deconectată |
Coduri TVA
| Cod | Descriere |
|---|---|
A | Cota TVA A (conform configurării terminalului) |
B | Cota TVA B (de obicei 20%) |
C | Cota TVA C |
D | Cota TVA D |
E | Cota TVA E |
_ | Scutit (fără TVA) |
Tipuri de plată (ACPS WSDL)
| Tip | Descriere |
|---|---|
"1" | NUMERAR |
"2" | CARD |
"3.1" | VAUCHER |
"3.2" | CEC / Certificat valoric |
"3.3" | TICHET — plata cu document de valoare prestabilită (MDL) |
"5" | TME — tichet de masă pe suport electronic |
"6" | ABONAMENT |
"7" | ALT IP (alt instrument de plată) |
"8.1" | Credit |
"8.2" | Leasing |
"8.3" | Avans |
"8.4" | Arvună |
"8.5" | Gaj |
"8.8" | Compensare |
"8.9" | Alt mod |
Tipuri de operațiuni fiscale
| Tip | Descriere |
|---|---|
receipt | Bon fiscal (vânzare) |
cash_in | Depunere numerar |
cash_out | Retragere numerar |
refund | Rambursare/retur |
x_report | Raport X |
z_report | Raport Z |
Stări ale operațiunilor fiscale
| Stare | Descriere |
|---|---|
pending | Creată, încă nu a fost trimisă la MEV |
sent | Trimisă la MEV, în așteptarea răspunsului |
success | Procesată cu succes de MEV |
failed | MEV a returnat o eroare |
offline | Stocată local (MEV inaccesibil) |
Obiectul Defalcare TVA
{
"B": {
"code": "B",
"percent": 20.0,
"vatAmount": 7.50,
"taxableBase": 37.50,
"gross": 45.00
}
}
| Câmp | Tip | Descriere |
|---|---|---|
code | string | Codul cotei TVA |
percent | number | Procentul TVA |
vatAmount | number | Suma TVA |
taxableBase | number | Suma netă (fără TVA) |
gross | number | Suma brută (cu TVA) |
Note
- Toate sumele monetare sunt în MDL (Lei moldovenești) ca
numbercu precizie de 2 zecimale. - Toate marcajele temporale sunt în format ISO 8601 UTC.
- Serverul utilizează un mecanism de blocare a operațiunilor fiscale — doar o singură operațiune fiscală (vânzare, depunere/retragere, raport Z/X) poate rula simultan. Cererile concurente vor aștepta până la 30 de secunde înainte de a returna
429 BUSY. - Modul offline: Când MEV (serverul autorității fiscale) este inaccesibil, operațiunile fiscale sunt stocate local și sincronizate ulterior. Răspunsul va avea
isOffline: trueșimevId: null. - Printarea bonurilor este de tip fire-and-forget — răspunsul API nu așteaptă finalizarea printării.
Colecții Postman
Două colecții, pentru cele două API-uri distincte. Se importă cu Import → File.
| Colecție | Ce conține | Descarcă |
|---|---|---|
| API terminal | Referința API-ului casei, în 28 de cereri: vânzări, numerar, rapoarte X/Z și periodice, tipărire, catalog, anulări și rambursări pe card, loturi de livrare. Fiecare cerere are câmpurile cererii și ale răspunsului, erorile cu statusul HTTP și exemple. Același API pe Android și pe PC-ECC (Windows); unde diferă, descrierea cererii o spune. | posfix-terminal-api.postman_collection.json |
| API public de integrare | Cele 24 de cereri prin care sistemul tău extern (magazin online, ERP) citește și scrie datele comerciantului: catalog, stoc, prețuri, clienți, comenzi, rapoarte Z, webhook-uri. | posfix-integration-api.postman_collection.json |
API terminal
Completează variabilele colecției:
baseUrl→http://<ip-terminal>:4567în rețeaua locală, sauhttps://api.posfix.md/api/relay/<publicId>prin relay — adresa o vezi pe casă, în fereastra modului ProviderapiKey→ cheia de pe terminal (Setări → Developer → Arată cheia API)
Apasă pe numele colecției în Postman ca să vezi descrierea ei: harta completă a erorilor,
regulile de reluare cu Idempotency-Key și tabelele de referință.
POST /api/reports/z nu se poate anula și resetează contoarele zilei. Nu-l rula ca
test pe un terminal în producție.
Nu e nevoie să deschizi tura: terminalul o deschide la prima vânzare sau operațiune cu numerar. Ziua se închide cu raportul Z.
API public de integrare
Cheia se creează în Control Panel → Chei API de integrare și se afișează în clar
o singură dată, la creare. Pune-o în variabila apiKey; se trimite pe fiecare
cerere ca X-Posfix-Api-Key.
Fiecare cheie primește doar permisiunile (scopes) alese la creare — descrierea fiecărei
cereri spune de care are nevoie. Fără scope-ul cerut, răspunsul e 403.
API-ul cere modulul «API Integrare» activ pe comerciant. Fără el răspunde 403
chiar și cu o cheie validă și cu scope-ul corect.
Comerciantul nu se trimite ca parametru: organizația vine din cheie, deci nu se pot
citi datele altcuiva. Începe cu GET /api/public/v1/ping — confirmă cheia,
comerciantul și scope-urile.