Reconciliere e-Factura ↔ SAF-T
Compară facturile pe care le-ai emis cu ce apare în fişierul SAF-T şi arată nepotrivirile în ambele sensuri: facturi lipsă din D406 şi înregistrări din D406 fără factură.
Corpul cererii
Se trimite ca JSON, în corpul cererii (Content-Type: application/json) — nu în şirul de interogare.
{id, xml}. Cu id, rândurile din lipsa_in_saft, diferente_valoare şi numere_duplicate poartă identificatorul tău. Un element care nu e nici XML, nici {id, xml} întoarce 422 cu poziţia lui.
{
"saft": "@saft-d406.xml",
"facturi": [
"@efactura.xml"
]
}
În exemplu, @saft-d406.xml, @efactura.xml ţin locul unor documente întregi: trimiţi conţinutul fişierului — XML-ul ca text sau base64, un PDF ca base64 — nu numele lui.
{
"saft": "@saft-d406.xml",
"facturi": [
"@efactura.xml",
"@efactura-stornare.xml"
]
}
În exemplu, @saft-d406.xml, @efactura.xml, @efactura-stornare.xml ţin locul unor documente întregi: trimiţi conţinutul fişierului — XML-ul ca text sau base64, un PDF ca base64 — nu numele lui.
{
"saft": "@saft-d406.xml",
"facturi": [
"@efactura-stornare.xml"
]
}
În exemplu, @saft-d406.xml, @efactura-stornare.xml ţin locul unor documente întregi: trimiţi conţinutul fişierului — XML-ul ca text sau base64, un PDF ca base64 — nu numele lui.
Parametri de interogare
Cum se comportă
- Compară facturile emise (XML-uri e-Factura) cu facturile de vânzare raportate în fișierul SAF-T (D406,
SourceDocuments/SalesInvoices), pe numărul de factură. Prinde ce nu se leagă între cele două raportări: facturi într-o parte dar nu în cealaltă, și totaluri (cu TVA) care diferă. - Corp JSON:
{saft: "<xml>", facturi: ["<xml>", ...]}(XML brut sau base64). Se potrivesc pe număr, iar sumele se compară în bani întregi (fără capcanele virgulei mobile). Pe partea e-Factura se citeșteTaxInclusiveAmount(BT-112), care are aceeași semantică cuGrossTotaldin SAF-T — nuPayableAmount, care scade avansurile încasate și ar produce diferențe false. - Dacă același număr apare de două ori pe aceeași parte (tipic o factură și un storno cu același număr), rândul e raportat în
numere_duplicateîn loc să fie suprascris silențios. - Zero retenție și fără SPV — totul e in-memory; nu depune nimic.
La ce folosește
- Verifici că SAF-T-ul lunii conține exact facturile emise prin e-Factura, cu aceleași sume, înainte de depunere.
- Găsești rapid factura lipsă sau suma greșită dintre sute de documente.
Structura răspunsului
true dacă există cel puțin o nepotrivire.
facturi_efactura, facturi_saft, lipsa_in_saft, lipsa_in_efactura, diferente_valoare, numere_duplicate.
[{id?,numar,tip,total}]; id apare doar dacă l-ai trimis.
[{numar,total}].
[{id?,numar,efactura,saft,diferenta}].
[{id?,numar,sursa,tip}].
Exemple de răspuns
body: {"saft": "@saft-d406.xml", "facturi": ["@efactura.xml"]}
{
"data": {
"are_diferente": true,
"sumar": {
"facturi_efactura": 1,
"facturi_saft": 2,
"lipsa_in_saft": 0,
"lipsa_in_efactura": 1,
"diferente_valoare": 0,
"numere_duplicate": 0
},
"lipsa_in_saft": [],
"lipsa_in_efactura": [
{
"numar": "FCT-2026-0143",
"total": 1210
}
],
"diferente_valoare": [],
"numere_duplicate": []
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d87c-724c-9897-cd8c69f79a4e"
}
}
body: {"saft": "@saft-d406.xml", "facturi": ["@efactura.xml", "@efactura-stornare.xml"]}
{
"data": {
"are_diferente": true,
"sumar": {
"facturi_efactura": 2,
"facturi_saft": 2,
"lipsa_in_saft": 1,
"lipsa_in_efactura": 1,
"diferente_valoare": 0,
"numere_duplicate": 0
},
"lipsa_in_saft": [
{
"numar": "STN-2026-0007",
"tip": "CreditNote",
"total": 242
}
],
"lipsa_in_efactura": [
{
"numar": "FCT-2026-0143",
"total": 1210
}
],
"diferente_valoare": [],
"numere_duplicate": []
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d882-736e-919d-8f6e74d3cc14"
}
}
body: {"saft": "@saft-d406.xml", "facturi": ["@efactura-stornare.xml"]}
{
"data": {
"are_diferente": true,
"sumar": {
"facturi_efactura": 1,
"facturi_saft": 2,
"lipsa_in_saft": 1,
"lipsa_in_efactura": 2,
"diferente_valoare": 0,
"numere_duplicate": 0
},
"lipsa_in_saft": [
{
"numar": "STN-2026-0007",
"tip": "CreditNote",
"total": 242
}
],
"lipsa_in_efactura": [
{
"numar": "FCT-2026-0142",
"total": 847
}
],
"diferente_valoare": [],
"numere_duplicate": []
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d889-7047-b8de-15b09f9de9bd"
}
}
Coduri de eroare
| Cod | Slug | Când apare |
|---|---|---|
| 401 | neautentificat | Token lipsă, invalid, expirat sau revocat. |
| 403 | feature_indisponibil | Planul curent nu include funcţia de care ţine ruta. |
| 422 | xml_invalid | Lipsește saft sau facturi, sau un document nu e XML valid; peste 5000 de facturi. |
| 429 | cota_depasita | Cota 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": "Lipsește saft sau facturi, sau un document nu e XML valid; peste 5000 de facturi.",
"camp": null,
"request_id": "0199c1f0-6e1a-7c3d-9b2f-4a8e5d1c7b04"
}
}