1. Home
  2. Guides
  3. Parse received e-invoices

Read received e-invoices into JSON

Businesses in Germany, France and Belgium now receive XRechnung, ZUGFeRD, Factur-X and Peppol BIS files, and the software they use has to turn those files into data: who sent the invoice, what was bought, how much VAT, when it is due. This page explains what is in those files, what goes wrong when you parse them yourself, and how to do it with one API call.

Updated 21 October 2026 · Last reviewed 21 October 2026

In brief

POST the file (the XML, or the PDF with the XML inside) to /api/v1/parse and you get the invoice as JSON: seller, buyer, lines, VAT breakdown and totals, a list of any values the JSON has no field for, and the official validation report, in one call. It reads XRechnung (UBL and CII), ZUGFeRD 2.x and Factur-X, Peppol BIS Billing 3.0 and plain EN 16931. Files are processed in memory and never stored.

Why software has to read e-invoices now

  • Germany: since 1 January 2025 every business must be able to receive e-invoices from other businesses, and an email inbox is enough to receive them (German mandate). What arrives is XRechnung or ZUGFeRD.
  • France: since 1 September 2026 every business subject to VAT must be able to receive e-invoices, through an approved platform; every platform accepts UBL, CII and Factur-X (French mandate).
  • Belgium: since 1 January 2026 invoices between Belgian businesses are structured e-invoices over Peppol, as Peppol BIS Billing 3.0 (Belgian mandate).

Bookkeeping, expense, procurement and accounts-payable tools that used to read PDFs with OCR now get the data itself, already structured, as long as they can read the XML.

What arrives, and where the data is

You receiveSyntaxWhere the invoice data is
XRechnung (XML)UBL 2.1 or CIIThe file itself
ZUGFeRD 2.x / Factur-X (PDF)CIIfactur-x.xml attached to the PDF/A-3 (ZUGFeRD 2.0: zugferd-invoice.xml)
XRechnung as a hybrid PDFCIIxrechnung.xml attached to the PDF
Peppol BIS Billing 3.0 (XML)UBL 2.1The file itself
A plain PDF or a scanNoneNowhere: there is no structured data to read

All of them carry the same European model, EN 16931, in one of two XML syntaxes: UBL (root Invoice or CreditNote) and UN/CEFACT CII (root CrossIndustryInvoice). The specification identifier (BT-24, cbc:CustomizationID in UBL, the guideline ID in CII) says which national rules apply on top.

What goes wrong when you parse them yourself

  • Two syntaxes, different paths for everything. The seller's VAT ID is cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID in UBL and ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID with schemeID="VA" in CII. Every field is like that, so you write and maintain two readers.
  • Dates. UBL writes 2026-10-21; CII writes <udt:DateTimeString format="102">20261021</udt:DateTimeString>.
  • VAT exemption reasons (reverse charge, intra-community supply, export) are stated once per VAT category in the breakdown, not on the lines that use them.
  • Credit notes are a different root element in UBL (CreditNote, with CreditNoteLine and CreditedQuantity) and type code 381 in CII.
  • Levels without lines. Factur-X MINIMUM and BASIC WL carry totals but no line items. In Germany they don't count as e-invoices (BMF FAQ, question 7), but they still arrive.
  • Totals. A sender's rounding can differ from a recalculation by a cent. Book the stated amounts and flag the difference rather than silently using either.
  • Security. These files come from outside. Refuse DOCTYPE declarations and external entities before parsing, or an invoice can read files from your server (OWASP on XXE).
  • Values your data model has no place for. A second identifier, item classifications, line notes: dropping them silently loses information someone may need later.

Parse it with one API call

curl https://validate.invoir.dev/api/v1/parse \
  -H "Authorization: Bearer $INVOIR_API_KEY" \
  -F file=@received-invoice.pdf

The answer, shortened:

{
  "status": "valid",
  "format": "PDF · Factur-X / ZUGFeRD EN 16931 (COMFORT)",
  "typeCode": "380",
  "invoice": {
    "profile": "factur-x", "conformance": "en16931", "type": "invoice",
    "number": "RE-2026-0042", "issueDate": "2026-10-19", "dueDate": "2026-11-18", "currency": "EUR",
    "seller": { "name": "Musterbau GmbH", "vatId": "DE123456789", "address": { "city": "München", "country": "DE" } },
    "buyer": { "name": "Beispiel AG", "reference": "PO-4711" },
    "lines": [ { "description": "Beratung Softwarearchitektur", "quantity": 12.5, "unit": "HUR", "unitPrice": 140, "vatRate": 19 } ],
    "payment": { "means": "credit_transfer", "iban": "DE89370400440532013000" }
  },
  "totals": { "currency": "EUR", "taxExclusive": 2912.20, "vat": 538.96, "taxInclusive": 3451.16, "due": 3451.16 },
  "unmapped": [],
  "warnings": [],
  "validation": { "status": "valid", "checks": [ "…" ] }
}
  • invoice is the same JSON that POST /invoices takes. Map it into your own model, or send it back to issue a document with the same content.
  • totals are the amounts as the document states them, VAT breakdown included: the numbers to book.
  • unmapped lists every value the JSON has no field for, with its path in the XML, so nothing disappears without a trace.
  • warnings say what reading noticed: stated totals that differ from a recalculation, a credit note, a document without lines.

A successful parse counts as one document; the free plan includes 25 a month, and test keys are free for 25 calls a day. Every field and error is in the API docs.

Check before you book

Every parse also runs the official rules, the same as the free validator: the KoSIT validator for XRechnung, the CEN and Peppol Schematron, Mustang for Factur-X and ZUGFeRD, veraPDF for the PDF. status says whether the invoice is valid, and each finding has its rule ID, such as BR-DE-15 for a missing buyer reference. An invalid invoice is still read, so you can store it and send the findings back to whoever issued it. Validation isn't a legal precondition in Germany, but the Federal Ministry of Finance calls it sensible (BMF FAQ, question 7).

From an email inbox, without code

Most e-invoices still arrive by email. In Make or Zapier, combine the tool's own email trigger with Invoir's Parse operation: new email with an attachment, then Parse e-invoice, then a row in a spreadsheet or a bill in your accounting tool. The n8n node gets the same operation in its next release.

Frequently asked questions

Can it read a normal PDF invoice?
No. A PDF without the invoice XML attached has no structured data, and Invoir doesn't do OCR. Ask the sender for ZUGFeRD, Factur-X or XRechnung: in Germany, France and Belgium business customers can increasingly insist on it.
Which formats can it read?
XRechnung (UBL and CII, also as a hybrid PDF), ZUGFeRD 2.x and Factur-X in every level, Peppol BIS Billing 3.0, and plain EN 16931 UBL or CII. ZUGFeRD 1.0, retired in 2019, can be validated but not parsed.
Is the invoice stored?
No. The file is processed in memory for the request and discarded; neither its content nor its name is logged.
What happens with an invalid invoice?
It is read anyway. status is invalid and the validation report lists every error with its rule ID, so you can decide whether to book it or send it back.
What does it cost?
Each successful parse counts as one document on your plan: 25 a month free, then from €9 a month plus VAT for 300 (pricing). Errors don't count, and neither do test keys (25 calls a day).
Check a file in your browser, or over the API.

The free validator runs the official rules (KoSIT, CEN and Peppol Schematron, Mustang, veraPDF) and lists every error with its rule ID. Nothing is stored. The same check is one HTTP call with a free API key: 25 documents a month, no credit card.

Sources

More guides