Emiți facturi conforme, printr-un apel.
Transformă un JSON de business în XML CIUS-RO valid, îl validează cu Schematron-ul oficial și îl randează PDF — totul printr-un API, fără să stochezi nimic.
Nu e un set de date, ci un instrument. Trimiți factura ca obiect, primești înapoi XML-ul, verdictul de validare și, la cerere, PDF-ul. Procesarea e în memorie; conținutul nu atinge un disc de-al nostru.
{
"furnizor": { "cui": "RO12345678", // obiectul tău de business
"client": { "cui": "RO87654321" },
"linii": [ { "cantitate": 3, "pret": 100 } ]
}
// → { valid: true, xml: "<Invoice…", meta: { totals } }
- Standard
- CIUS-RO / UBL 2.1
- Reguli
- EN16931 + RO-eFactura
- Operațiuni
- build · validate · parse · render
- Nomenclatoare
- UN/ECE, cote TVA
- Retenție
- niciuna
Conformitatea e-Factura e grea. Și nu e produsul tău.
Între obiectul tău de business și un XML pe care ANAF îl acceptă se află un strat de reguli care se schimbă și pe care cineva trebuie să-l țină la zi.
CIUS-RO / UBL
Factura nu e un JSON, ci un XML UBL 2.1 cu zeci de elemente ordonate, spații de nume și cardinalități stricte. O virgulă în plus, un câmp lipsă, și fișierul e respins.
Nomenclatoare
Coduri de unitate de măsură UN/ECE, categorii și cote de TVA, tipuri de taxă, coduri de țară. Liste oficiale, cu valori permise, pe care trebuie să le mapezi și să le actualizezi.
Zeci de cazuri fiscale
Taxare inversă, scutiri cu drept de deducere, livrare intracomunitară, export, TVA la încasare, avansuri, storno. Fiecare are propriile reguli despre ce câmpuri apar și ce coduri sunt permise.
Schematron
Validarea reală nu e împotriva unei scheme XSD, ci a regulilor de business EN16931 și RO-eFactura, scrise în Schematron. Sute de aserțiuni care trebuie rulate corect.
BR-RO
Peste regulile europene, ANAF adaugă propriile constrângeri naționale — cod fiscal, adresă, coduri specifice. Trec regulile EN și pică cele RO, sau invers.
Reguli care se schimbă
Specificația se revizuiește, nomenclatoarele se completează, aserțiunile se ajustează. Ce era valid anul trecut poate fi respins azi, iar tu afli din refuz, nu din anunț.
Patru operațiuni și un nomenclator.
Fiecare e un apel POST independent. Le folosești pe cea de care ai nevoie; nu ești obligat să treci prin toate.
/build
Construiește
Trimiți factura ca JSON de business, primești XML CIUS-RO valid. Ordinea elementelor, spațiile de nume, totalurile și codurile sunt puse corect de noi, din obiectul tău.
/validate
Validează
Rulezi un XML existent prin Schematron-ul oficial local, plus o verificare numerică proprie a totalurilor. Primești verdict, lista de reguli picate și diferența exactă.
/parse
Parsează
Un XML CIUS-RO primit devine un JSON curat, cu câmpurile despachetate — furnizor, client, linii, taxe, totaluri — ca să-l poți citi fără să atingi UBL.
/render
Randează
Din factură sau din XML iese un PDF lizibil pentru om, generat local (dompdf). Vizualizarea pe care o dai clientului tău, fără un serviciu extern de randare.
/codes
Nomenclatoare
Listele oficiale pe care le acceptă factura — unități de măsură, categorii și cote de TVA, tipuri de document, coduri de țară — servite ca referință, ca să validezi din formular.
Facturile tale nu ajung nicăieri. Nici la noi, nici la ANAF.
Ăsta e răspunsul la „de ce aș trimite facturile mele la un terț”. Pentru că, practic, nu le trimiți nicăieri — procesăm și uităm.
Procesare în memorie
Payload-ul nu se scrie niciodată pe disc. Intră în request, e transformat în memorie și dispare când răspunsul pleacă. Nu există un fișier al facturii tale la noi.
Validare locală
Schematron-ul oficial rulează la noi, pe serverul care ține răspunsul tău. Nu trimitem factura la ANAF ca să aflăm dacă e validă — regulile sunt aici, verdictul e local.
Loguri fără conținut
Ce reținem e un cod de rezultat și o durată — atât. Numele clientului tău, sumele, liniile facturii nu intră în niciun log, nici la noi, nici la un serviciu de observabilitate.
Nici măcar XML-ul
Un header opțional îți spune să nu returnăm nici XML-ul, doar verdictul și totalurile. Pentru integrări unde vrei validarea, dar preferi ca documentul să nu treacă întreg prin răspuns.
Nu-ți spunem doar „invalid”. Îți spunem exact ce și cu cât.
Rulăm regulile oficiale, complet, local — și adăugăm diagnosticul numeric pe care validatorul ANAF nu ți-l dă.
Schematron oficial
Rulăm setul complet de reguli EN16931 + CIUS-RO + RO-eFactura, aceleași aserțiuni pe care le folosește ANAF, executate local. Dacă o factură trece la noi, trece pentru că respectă regulile, nu pentru că am fost indulgenți.
Verificare numerică proprie
Peste Schematron adăugăm o verificare a totalurilor pe care o facem noi: bază, TVA, total pe linie, total pe document. Când ceva nu se potrivește, îți spunem câmpul și diferența exactă — 0,01 lei din rotunjire, nu „undeva e o problemă”.
Diagnostic, nu doar verdict
Validatorul ANAF îți dă „respins” și un cod. Noi îți dăm regula picată în text, câmpul implicat și, la totaluri, valoarea așteptată față de cea primită. Diferența dintre a ști că e o problemă și a ști unde e.
Cross-check ANAF opțional
Dacă vrei confirmarea de la sursă, poți cere un cross-check la validatorul ANAF pentru o factură anume. Rămâne opțional și explicit: implicit, nimic nu pleacă de la noi către ANAF.
De la B2B simplu la storno în valută.
Cazurile fiscale reale, nu doar exemplul din manual. Fiecare cu codurile și câmpurile corecte, gata construite.
Acoperim standardul CIUS-RO complet: FACT1 pentru facturi și FCN pentru note de credit. Dacă întâlnești un caz pe care nu-l tratăm corect, scrie-ne — cazurile reale au prioritate în ce construim.
Un obiect de factură intră. XML-ul valid iese.
Trimiți factura ca JSON de business, primești verdictul, XML-ul și totalurile calculate. Fără SDK obligatoriu — clientul HTTP pe care îl ai deja.
# build: un obiect minim de factură → XML CIUS-RO valid
curl "https://oneapi.ro/api/anaf/v1/efactura/build" \
-H "Authorization: Bearer $ONEAPI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tip": "FACT1",
"moneda": "RON",
"furnizor": { "cui": "RO12345678", "nume": "Furnizor SRL" },
"client": { "cui": "RO87654321", "nume": "Client SRL" },
"linii": [
{ "descriere": "Consultanță", "cantitate": 3, "pret": 100, "cota_tva": 19 }
]
}'
# → 200 OK
{
"valid": true,
"xml": "<Invoice xmlns=…>…</Invoice>",
"meta": { "totals": { "baza": 300.00, "tva": 57.00, "total": 357.00 } }
}
Regula picată, câmpul și diferența
Un răspuns de eroare nu-ți dă doar „invalid”. Îți dă codul regulii, textul ei, câmpul implicat și — la totaluri — valoarea așteptată față de cea primită. Suficient ca să corectezi din prima, nu să ghicești.
HTTP/1.1 422 Unprocessable Content
{ "valid": false,
"erori": [ {
"regula": "BR-CO-15",
"mesaj": "Total nu corespunde bazei + TVA.",
"camp": "totals.total",
"asteptat": 357.00, "primit": 357.01
} ] }
Înainte să trimiți prima factură.
Restul, în întrebări frecvente și în documentație.