Ghid pentru dezvoltatori: integrare eFactura ANAF
Ghid tehnic: cât efort cere integrarea directă cu ANAF (UBL XML, validare, retry, endpoint-uri SPV) și cât de simplu emiți eFactura prin API-ul Fint, cu exemple de cod.
eFactura este obligatorie în România pentru toate tipurile de tranzacții - B2B, B2C și B2G - iar ca dezvoltator o poți integra în aplicația ta în mai multe moduri. În acest ghid comparăm două abordări: integrarea directă cu sistemul ANAF/SPV și integrarea prin API-ul specializat Fint. Ambele ajung în același loc - un document validat de ANAF - dar efortul de implementare și de mentenanță diferă enorm. Acest ghid trece prin ce presupune, concret, fiecare abordare, cu exemple de cod, ca să poți estima corect timpul de dezvoltare.
Dacă vrei o privire de ansamblu, mai puțin tehnică, ai și articolul eFactura fără bătăi de cap. Aici intrăm în detaliile care contează pentru echipa de dezvoltare.
Integrarea directă cu ANAF: ce trebuie să construiești
O integrare proprie, de la zero, nu este un simplu apel HTTP. Înseamnă să construiești și să menții mai multe componente, fiecare cu propriile capcane.
1. Înțelegerea standardului UBL 2.1 și CIUS-RO
ANAF nu acceptă un JSON simplu. Factura trebuie exprimată în UBL 2.1 (Universal Business Language), în plus respectând regulile naționale CIUS-RO peste standardul european EN 16931. Practic, trebuie să înțelegi zeci de elemente XML din două namespace-uri diferite (cbc: pentru componente de bază, cac: pentru componente agregate), să știi care câmpuri sunt obligatorii, ce coduri de țară, de monedă și de TVA sunt permise și cum se leagă între ele.
2. Construirea generatorului de XML
Datele tale de business (emitent, client, linii, TVA) trebuie transformate într-un XML de forma următoare - și acesta e doar un fragment simplificat, un document real are mult mai multe elemente obligatorii:
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1</cbc:CustomizationID>
<cbc:ID>FAC-2026-001</cbc:ID>
<cbc:IssueDate>2026-06-01</cbc:IssueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyTaxScheme>
<cbc:CompanyID>RO12345678</cbc:CompanyID>
<cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
</cac:PartyTaxScheme>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="RON">19.00</cbc:TaxAmount>
</cac:TaxTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="H87">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount>
</cac:InvoiceLine>
</Invoice>
Nu e suficient să produci XML valid sintactic: valorile trebuie să fie coerente între ele (totalurile de linie să dea totalul documentului, TVA-ul să corespundă cotei, moneda să fie consistentă). Orice generator serios trebuie să acopere toate tipurile de documente și toate cazurile de TVA.
3. Ciclul de validare: multe încercări eșuate
ANAF validează documentul cu reguli de schematron peste EN 16931 și CIUS-RO. Prima ta factură aproape sigur va fi respinsă, iar mesajele arată cam așa:
{
"stare": "nok",
"Messages": [
{ "message": "[BR-CO-10] Suma valorilor nete de linie nu este egala cu valoarea totala neta a documentului." },
{ "message": "[BR-S-08] TVA pe categorie nu corespunde cotei declarate pe linii." }
]
}
Fiecare astfel de regulă (există sute) trebuie înțeleasă, reprodusă local și acoperită cu teste. Ciclul „generezi → trimiți → citești eroarea → corectezi generatorul” se repetă până când toate documentele tale reale trec - și se redeschide de fiecare dată când ANAF actualizează specificațiile.
4. Endpoint-uri ANAF eterogene
Comunicarea cu SPV (Spațiul Privat Virtual) nu are un format unitar. Trebuie să te descurci cu:
- Autorizare OAuth 2.0 per companie, cu certificat digital calificat, plus reînnoirea periodică a token-ului - altfel apelurile se opresc.
- Răspunsuri în formate mixte: un upload îți întoarce un ID de încărcare, statusul se interoghează separat, iar documentul final se descarcă adesea ca
.zipcare conține XML-ul (semnat) plus semnătura ANAF - nu ca JSON. - Medii separate de test și de producție, cu URL-uri și credențiale diferite, pe care trebuie să le comuți corect.
5. Fiabilitate: serverele ANAF nu sunt mereu disponibile
SPV are perioade de indisponibilitate și de răspuns lent. O integrare de producție nu poate apela sincron și spera că merge - trebuie să construiești:
- Retry cu backoff exponențial pentru erorile temporare și timeout-uri.
- O coadă internă (queue) care ține documentele în așteptare și le reîncearcă ordonat, în loc să blocheze cererea utilizatorului.
- Idempotență, ca un retry să nu trimită de două ori aceeași factură și să genereze dubluri la ANAF.
- Monitorizarea statusului în fundal, de la
trimispână lavalidatsaurespins, pentru fiecare document.
Fiecare dintre acești pași cere studiu, testare și mentenanță continuă - mai ales la fiecare modificare a specificațiilor ANAF. Pentru multe echipe, asta înseamnă săptămâni de dezvoltare și un cost recurent de întreținere.
Aceeași integrare prin Fint: trimiți datele, primești documentul validat
Prin serviciul eFactura Fint, tot ce e mai sus - UBL, validare, endpoint-uri SPV, retry, coadă - este ascuns în spatele unui API REST cu payload JSON. Tu trimiți datele de business ale facturii; Fint construiește XML-ul, îl validează, îl trimite la ANAF și urmărește statusul. Autentificarea folosește două chei transmise ca headere: X-Org-Key (organizația) și X-Api-Key (compania).
Autorizarea companiei
Compania aprobă accesul în portalul ANAF printr-un link generat de API - fără să implementezi tu fluxul OAuth și fără să te ocupi de certificatul digital. Fint se ocupă apoi de partea tehnică a gestionării token-urilor.
curl -X POST https://api.fint.ro/v1/efactura/onboarding \
-H "X-Org-Key: org_key_here" \
-H "X-Api-Key: company_key_here"
Răspunsul conține un link pe care îl deschide reprezentantul companiei pentru a aproba accesul în SPV. Verifici oricând starea autorizării:
curl https://api.fint.ro/v1/efactura/consent \
-H "X-Org-Key: org_key_here" \
-H "X-Api-Key: company_key_here"
Trimiterea unei facturi
Trimiți datele de business ca JSON - fără UBL, fără XML construit manual:
curl -X POST https://api.fint.ro/v1/efactura/send \
-H "X-Org-Key: org_key_here" \
-H "X-Api-Key: company_key_here" \
-H "Content-Type: application/json" \
-d '{
"documentNumber": "FAC-2026-001",
"documentDate": "2026-06-01",
"currency": "RON",
"buyer": { "cui": "RO87654321" },
"lines": [
{ "description": "Servicii consultanță", "quantity": 1, "unitPrice": 100.00, "vatRate": 19 }
]
}'
Fint completează automat datele firmelor pe baza CUI-ului, generează UBL-ul conform CIUS-RO, îl validează înainte de trimitere și îl transmite la SPV. Răspunsul vine într-un envelope standard:
{
"status": "success",
"msg": null,
"reason": null,
"data": {
"uid": "5f2a9c14-...",
"documentNumber": "FAC-2026-001",
"state": "queued"
}
}
Verificarea statusului
Documentul parcurge automat stările pending → queued → sent → validated / rejected / failed. Nu trebuie să construiești tu logica de polling la SPV - interoghezi Fint după UID:
curl "https://api.fint.ro/v1/efactura/document?uid=5f2a9c14-..." \
-H "X-Org-Key: org_key_here" \
-H "X-Api-Key: company_key_here"
{
"status": "success",
"data": { "uid": "5f2a9c14-...", "state": "validated" }
}
La validated, documentul este oficial. La rejected, primești motivul într-un format lizibil și poți corecta datele pentru re-trimitere.
Descărcarea PDF sau XML
După validare, descarci reprezentarea PDF sau arhiva XML originală, ambele păstrate în Fint pentru audit:
curl "https://api.fint.ro/v1/efactura/download?uid=5f2a9c14-...&format=pdf" \
-H "X-Org-Key: org_key_here" \
-H "X-Api-Key: company_key_here"
Un mediu sandbox este disponibil pentru integrare și testare înainte de trecerea în producție, ca să nu experimentezi pe documente reale.
Fără UBL, fără generator de XML, fără cicluri de validare și fără logică de retry: datele de business intră, documentul conform iese.
Direct cu ANAF vs. Fint: comparație pentru dezvoltatori
| Aspect | Direct cu ANAF | Prin Fint |
|---|---|---|
| Documentație | Specificații dispersate și greu de urmărit pentru un dezvoltator nefamiliarizat cu modelul ANAF | Documentație structurată, cu exemple și standarde moderne (REST/JSON) |
| Format de date | UBL 2.1 XML (CIUS-RO), construit manual | JSON de business |
| Validare | O implementezi și o depanezi tu, iterativ | Automată, înainte de trimitere |
| Autorizare SPV | Implementezi tu OAuth + certificat + logica de reînnoire a token-ului, per companie | Un link de onboarding; Fint se ocupă de partea tehnică a token-urilor |
| Endpoint-uri | Formate mixte (upload, status, zip cu XML) | Un singur API REST unitar |
| Fiabilitate | Retry, coadă, idempotență - construite de tine | Gestionate de Fint în fundal |
| Mentenanță la schimbări ANAF | Responsabilitatea ta, continuă | Fint urmărește și aplică actualizările |
| Timp până la prima factură | Săptămâni sau luni | Ore |
Când merită fiecare abordare
Integrarea directă poate avea sens în cazuri punctuale - de exemplu când o cerință strictă îți impune să păstrezi tot fluxul în propria infrastructură, sau când ai constrângeri de arhitectură foarte specifice și o echipă dedicată care să întrețină componenta pe termen lung. Pentru majoritatea aplicațiilor însă - unde ai deja datele facturii și vrei conformitate rapidă, fără să devii expert în UBL și în specificațiile SPV - integrarea prin Fint livrează același rezultat cu o fracțiune din efort și fără costul de mentenanță recurent.
Nici volumele mari sau standardele ridicate nu impun o integrare proprie. Planul Enterprise acoperă volume negociate, SLA contractual, suport dedicat și onboarding tehnic asistat pentru integrări complexe - astfel încât și organizațiile cu cerințe ridicate de securitate și disponibilitate rămân pe API-ul Fint.
Creează un cont Fint și activează eFactura ca să emiți documente conforme din câteva apeluri API, fără să te ocupi de detaliile tehnice ANAF.