oneapi
Autentificare
Anaf v1 / e-Factura

Validează factura

Verdictul pe trei straturi — XSD, regulile europene EN 16931 şi cele româneşti CIUS-RO — pentru o factură deja făcută. Fiecare eroare vine cu codul regulii, ca să ştii ce anume ai încălcat.

POST
https://oneapi.ro/api/anaf/v1/efactura/validate

Corpul cererii

Corpul cererii e documentul întreg, trimis brut (Content-Type: application/xml) — nu un obiect cu câmpuri.

Factură UBL CIUS-RO

efactura.xml application/xml · 4,0 KB — se trimite ca atare, în corpul cererii.

Factură în CII

efactura-cii.xml application/xml · 5,5 KB — se trimite ca atare, în corpul cererii.

Factură corectată

efactura-corectata.xml application/xml · 4,0 KB — se trimite ca atare, în corpul cererii.

Parametri de interogare

NumeTipDescriereValori acceptate
anafopțional boolean La 1 (sau validate=anaf) adaugă cross-check la validatorul ANAF; confirmarea apare în anaf_confirmation. Implicit, validare integral locală. ex. 1
viesopțional boolean La 1 verifică în VIES codul de TVA al cumpărătorului non-RO; rezultatul apare în vies şi nu afectează valid. Apel extern opţional — dacă VIES nu răspunde, state: unavailable. ex. 1

Cum se comportă

  • Documentul se poate trimite şi ca fişier: multipart/form-data cu câmpul fisier (curl -F fisier=@document.xml), în locul corpului brut. Conţinutul fişierului devine corpul cererii, deci rezultatul e identic; opţiunile rămân în query string, iar alt câmp de formular lângă fisier dă 422 camp_necunoscut.
  • Primeşte XML-ul unei facturi în corpul cererii şi întoarce verdictul de validare pe trei straturi, cumulativ: (1) well-formed — XML-ul se parsează; (2) o verificare numerică proprie, care recalculează totalurile şi raportează diferenţa exactă acolo unde sumele nu se leagă; (3) Schematron-ul oficial EN 16931 + CIUS-RO + RO-eFactura, rulat local prin Saxon.
  • Verificarea numerică proprie (stratul 2) e cea care prinde greşeala care doare cel mai des: un total care nu corespunde sumei liniilor. În loc de un simplu „invalid", răspunsul dă diferenţa exactă, ca să vezi dintr-o privire cât şi unde s-a rupt calculul.
  • Cu ?anaf=1 se adaugă un cross-check la validatorul ANAF, iar confirmarea lui apare separat în anaf_confirmation. Fără el, validarea e integral locală — acelaşi Schematron oficial, dar fără ca XML-ul să iasă din proces.
  • Cu ?vies=1 se verifică suplimentar, în VIES (Comisia Europeană), codul de TVA al cumpărătorului non-RO — util la livrările intracomunitare scutite (categoria K), unde scutirea e legală doar dacă partenerul are cod de TVA valid în alt stat membru. Schematron-ul verifică formatul; VIES confirmă că respectivul cod chiar există şi e activ. Rezultatul apare separat în vies şi nu afectează valid. E un apel extern, opţional: dacă VIES nu răspunde, câmpul întoarce state: unavailable şi validarea locală merge mai departe.
  • Un XML invalid nu e o eroare a cererii. Răspunsul e 200 cu valid: false şi lista de erori în errors[], fiecare cu cod, mesaj şi camp. „Invalid" fără să spui ce anume n-ajută pe cineva care încearcă să corecteze factura.
  • cod şi regula citată în mesaj pot să nu coincidă — de pildă cod: BR-RO-081 cu un mesaj care începe cu [BR-RO-080]. Nu e o eroare a noastră: schema oficială ROeFactura-UBL-validation-Invoice.xslt are aserţiuni distincte (adresa vânzătorului BT-35, adresa cumpărătorului BT-50) cu id-uri diferite, dar cu acelaşi prefix în text. Transmitem fidel ambele. Ia cod ca identificator al regulii, nu prefixul din text.
  • Zero retenţie: XML-ul primit nu se scrie şi nu se loghează; validarea e stateless.

La ce folosește

  • Verificarea unei facturi generate în altă parte, înainte de depunere în SPV.
  • Depanarea unui total care nu se leagă, folosind diferenţa exactă din stratul numeric.
  • Cross-check la ANAF (?anaf=1) pentru confirmare oficială, când verificarea locală nu e de ajuns.
  • Confirmarea în VIES (?vies=1) a codului de TVA al cumpărătorului la o livrare intracomunitară scutită (categoria K).

Structura răspunsului

CâmpTipDescriere
data.valid boolean Verdictul cumulat al celor trei straturi.
data.standard string Standardul detectat din XML: FACT1 sau FCN.
data.schema_version string Schema/standardul folosit la validare, când e disponibil (ex. FACT1 sau d390_v3.xsd); altfel null.
data.errors array Erorile de validare, fiecare {cod,mesaj,camp}. Gol când valid e true.
data.warnings array Avertismente neblocante, în acelaşi format.
meta.generat_la string Momentul la care s-a construit răspunsul (ISO 8601).
data.anaf_confirmation Rezultatul cross-check-ului ANAF {state,reason,messages,trace_id}; apare doar la ?anaf=1. state: ok/nok (verdictul ANAF) ori unavailable când validatorul n-a dat un verdict — atunci reason spune de ce: timeout, connection, http_<cod>, unintelligible_response (de obicei pagina de mentenanţă, servită cu HTTP 200), circuit_open, throttled_user, throttled_global. unavailable nu înseamnă nok.
data.vies Rezultatul verificării VIES {state,reason,country,number,name}; apare doar la ?vies=1, pentru un cumpărător non-RO. state: valid/invalid/unavailable. La unavailable, reason spune de ce n-a existat verdict: member_state_unavailable, busy, timeout, connection, http_<cod>, unintelligible_response, circuit_open, throttled_user, throttled_global. unavailable nu înseamnă invalid.

Exemple de răspuns

body: @efactura.xml

POSThttps://oneapi.ro/api/anaf/v1/efactura/validate
{
    "data": {
        "valid": true,
        "standard": "FACT1",
        "schema_version": "CIUS-RO 1.0.1 (EN16931)",
        "errors": [],
        "warnings": []
    },
    "meta": {
        "generat_la": "2026-10-06T23: 59: 42+03: 00"
    }
}

Coduri de eroare

CodSlugCând apare
401neautentificatToken lipsă, invalid, expirat sau revocat.
403feature_indisponibilPlanul curent nu include funcţia de care ţine ruta.
422xml_invalidCorpul nu e XML parsabil. Un XML valid-ca-structură dar neconform întoarce 200 cu valid: false.
429cota_depasitaCota lunară a planului a fost depăşită (vezi Retry-After).

Erorile modulului Anaf au acelaşi plic ca restul platformei, cu două câmpuri în plus: {eroare: {cod, mesaj, camp, request_id}}. eroare.cod e stabil şi e cel după care ramifici în cod; la validare (422) codul e specific cazului: xml_invalid, xml_nu_e_factura, unitate_necunoscuta, luna_invalida ş.a. camp arată câmpul vinovat, când se poate identifica.

{
    "eroare": {
        "cod": "xml_invalid",
        "mesaj": "Corpul nu e XML parsabil. Un XML valid-ca-structură dar neconform întoarce 200 cu valid: false.",
        "camp": "anaf",
        "request_id": "0199c1f0-6e1a-7c3d-9b2f-4a8e5d1c7b04"
    }
}