Differences between two documents
Two documents of the same type, field by field: what was added, what was removed and what changed. For seeing exactly what a correction brings over the original document.
Request body
Sent as JSON in the request body (Content-Type: application/json) — not in the query string.
a, raw XML or base64.
{
"a": "@efactura.xml",
"b": "@efactura-corectata.xml"
}
In this example, @efactura.xml, @efactura-corectata.xml stand in for whole documents: send the file content — XML as text or base64, a PDF as base64 — not its name.
{
"a": "@efactura.xml",
"b": "@efactura-stornare.xml"
}
In this example, @efactura.xml, @efactura-stornare.xml stand in for whole documents: send the file content — XML as text or base64, a PDF as base64 — not its name.
{
"a": "@etransport.xml",
"b": "@etransport-lic.xml"
}
In this example, @etransport.xml, @etransport-lic.xml stand in for whole documents: send the file content — XML as text or base64, a PDF as base64 — not its name.
{
"a": "@d100.xml",
"b": "@d100-rectificat.xml"
}
In this example, @d100.xml, @d100-rectificat.xml stand in for whole documents: send the file content — XML as text or base64, a PDF as base64 — not its name.
Query parameters
How it behaves
- Compares TWO ANAF documents of the same type and returns what changed, field by field — typically the "old version" against the "new version". Works across every product on the platform (e-Invoice, e-Transport, SAF-T, D declarations): the type is detected on its own from the root/namespace.
- JSON body:
{a: "<xml>", b: "<xml>"}(raw XML or base64). The comparison runs on the business JSON (the parser's output), not on raw XML, so every difference comes with a path made of named fields (linii.0.pret) rather than an XML node. - Lists are compared positionally, by index: a line inserted in the middle shows up as a chain of modifications plus one addition at the end. We do not guess the identity of list items.
- Nothing is interpreted fiscally — it reports strictly what differs. Past 500 differences the response is truncated (
trunchiat: true). - Zero retention and no SPV — everything is in-memory.
What it is for
- See exactly what changed between the original invoice and the corrected one, before you send the credit note or the new version.
- Check, before filing, what differs between the declaration you filed last month and the one you are preparing now.
- Internal audit: prove which fields changed between two versions of the same document.
Response structure
efactura, etransport, saft, declaratii).
true if there is no difference at all.
modificate, adaugate, sterse, total.
[{cale,inainte,dupa}].
b [{cale,valoare}].
a [{cale,valoare}].
true if more than 500 differences were found and the lists were cut.
Response examples
body: {"a": "@efactura.xml", "b": "@efactura-corectata.xml"}
{
"data": {
"tip": "e-Factura",
"produs": "efactura",
"identice": false,
"sumar": {
"modificate": 1,
"adaugate": 0,
"sterse": 0,
"total": 1
},
"modificate": [
{
"cale": "lines.0.quantity",
"inainte": 2,
"dupa": 3
}
],
"adaugate": [],
"sterse": [],
"trunchiat": false
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d891-7144-ae4c-bffcf733ff72"
}
}
body: {"a": "@efactura.xml", "b": "@efactura-stornare.xml"}
{
"data": {
"tip": "e-Factura",
"produs": "efactura",
"identice": false,
"sumar": {
"modificate": 6,
"adaugate": 1,
"sterse": 2,
"total": 9
},
"modificate": [
{
"cale": "type",
"inainte": "invoice",
"dupa": "credit_note"
}
],
"adaugate": [
{
"cale": "preceding_invoices",
"valoare": {
"_structura": "1 element(e)"
}
}
],
"sterse": [
{
"cale": "due_date",
"valoare": "2026-10-10"
}
],
"trunchiat": false
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d898-7234-a0ac-4a6c6def14ce"
}
}
body: {"a": "@etransport.xml", "b": "@etransport-lic.xml"}
{
"data": {
"tip": "e-Transport",
"produs": "etransport",
"identice": false,
"sumar": {
"modificate": 12,
"adaugate": 1,
"sterse": 1,
"total": 14
},
"modificate": [
{
"cale": "ref_declarant",
"inainte": "AVZ-2026-0142",
"dupa": "LIC-2026-0007"
}
],
"adaugate": [
{
"cale": "loc_final.ptf",
"valoare": "1"
}
],
"sterse": [
{
"cale": "loc_final.locatie",
"valoare": {
"_structura": "5 câmp(uri)"
}
}
],
"trunchiat": false
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d89f-71a0-8a74-4ea4ef66832d"
}
}
body: {"a": "@d100.xml", "b": "@d100-rectificat.xml"}
{
"data": {
"tip": "D100",
"produs": "declaratii",
"identice": false,
"sumar": {
"modificate": 3,
"adaugate": 0,
"sterse": 0,
"total": 3
},
"modificate": [
{
"cale": "total_plata",
"inainte": 2400,
"dupa": 3700
}
],
"adaugate": [],
"sterse": [],
"trunchiat": false
},
"meta": {
"generat_la": "2026-10-06T23: 59: 41+03: 00",
"request_id": "01a11303-d8a4-727f-9772-9fa1ef599056"
}
}
Error codes
| Code | Slug | When it occurs |
|---|---|---|
| 401 | neautentificat | Token missing, invalid, expired or revoked. |
| 403 | feature_indisponibil | The current plan does not include the feature the route depends on. |
| 422 | xml_invalid | Missing a or b; a document is not valid XML or is unrecognized; the two documents are of different types. |
| 429 | cota_depasita | The plan's monthly quota has been exceeded (see Retry-After). |
Errors in the Anaf module use the same envelope as the rest of the platform, with two extra fields: {eroare: {cod, mesaj, camp, request_id}}. eroare.cod is stable and is what you branch on; on validation (422) the code is case-specific: xml_invalid, xml_nu_e_factura, unitate_necunoscuta, luna_invalida and so on. camp points at the offending field when one can be identified.
{
"eroare": {
"cod": "xml_invalid",
"mesaj": "Missing a or b; a document is not valid XML or is unrecognized; the two documents are of different types.",
"camp": null,
"request_id": "0199c1f0-6e1a-7c3d-9b2f-4a8e5d1c7b04"
}
}