EU E-Invoice Parser — Line Items, VAT IDs, Totals avatar

EU E-Invoice Parser — Line Items, VAT IDs, Totals

Pricing

from $2.00 / 1,000 e-invoices

Go to Apify Store
EU E-Invoice Parser — Line Items, VAT IDs, Totals

EU E-Invoice Parser — Line Items, VAT IDs, Totals

EU e-invoices (XRechnung, ZUGFeRD, Factur-X, PEPPOL UBL) to JSON: invoice number, dates, seller and buyer VAT IDs, IBAN, net, tax and gross totals, line items, reconciliation checks and XML evidence. Input: XML or hybrid PDF by URL, key-value store or sample. Pay per result. No login.

Pricing

from $2.00 / 1,000 e-invoices

Rating

0.0

(0)

Developer

architek.earth

architek.earth

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 hours ago

Last modified

Share

Recorded run: 2 invoices from 2 sample files in 5 seconds (2026-10-22, build 0.0.6, run TptAKSTt91t9Lo4aL). A bounded canary sample, not a full-catalogue benchmark.

architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.

EU e-invoice line items, VAT IDs and totals as JSON: give it XRechnung, ZUGFeRD, Factur-X or PEPPOL UBL files (XML, or PDF with the XML embedded) by URL or from a key-value store, and get one row per invoice read from the invoice's own XML.

SourceMarketFromStandout fields
Your e-invoice files (EN 16931 CII and UBL XML, hybrid PDF)EU$2.00 / 1,000 invoicesvendorVatId / buyerVatId / iban, lineItems, checks / evidence

✅ Why choose this scraper

Convert XRechnung and PEPPOL UBL XML to JSON

UN/CEFACT CII (ZUGFeRD 2.x, Factur-X, XRechnung CII), OASIS UBL 2.1 (XRechnung UBL, PEPPOL BIS 3, invoices and credit notes) and legacy ZUGFeRD 1.0 come back in the same row shape: documentNumber, issueDate, vendorName, vendorVatId, buyerVatId, iban, subtotal, taxTotal, total. The build log records 70 of 70 standalone XML invoices from the public ZUGFeRD test corpus parsed on 2026-10-18.

Extract the invoice data from ZUGFeRD and Factur-X PDFs

For a hybrid PDF the embedded XML is read, and einvoice.container is "pdf". A PDF with no e-invoice XML inside gets a free NOT_AN_EINVOICE status row instead of a guessed row.

Check that invoice totals and line items add up

checks.totalsReconciled (net + tax = gross) and checks.lineItemsReconciled (lines = line total) are set on every invoice. An invoice that does not add up is returned as written with status: "inconsistent" and a plain-language warnings entry; no number is corrected.

Catch a printed PDF total that disagrees with its XML

On hybrid PDFs the XML gross, net and tax are looked up on the printed page (checks.xmlTotalInPdfText, xmlSubtotalInPdfText, xmlTaxInPdfText). In the public corpus this flagged 4 published sample PDFs whose page disagrees with its own XML, for example a printed 963,12 against an XML 963.11.

Trace every value back to its XML element

evidence names the element each field came from, for example "xml: LegalMonetaryTotal/TaxInclusiveAmount". A field the XML does not have is omitted; the test suite requires every emitted value to appear as text in its source XML.

⚠️ Worth knowing up front

  • E-invoices only. Ordinary PDF invoices without embedded XML, and scans or images, are not read: they get a free NOT_AN_EINVOICE status row. There is no OCR.
  • Italy (FatturaPA), Poland (KSeF) and Spain (Facturae) are not supported; they are not EN 16931 CII or UBL.
  • It does not validate against the official schematron rules. Use KoSIT or the official validators for compliance checks.
  • Fields are omitted, never null, when the invoice does not contain them. taxRate is omitted when several tax rates apply, amountDue appears only when it differs from total, and values stay in the invoice's language (German line descriptions stay German).
  • Up to 500 distinct references per run, files up to 64 MB. Each URL download is tried up to 3 times within 120 seconds; URLs to private, local or reserved network addresses are refused. A parsed invoice larger than one 9 MB dataset item drops its line items and is charged as document.
  • A run stops cleanly 30 seconds before its timeout (TIME_LIMIT), at your spending limit (BUDGET_LIMIT) or on abort (ABORTED), keeping what it delivered; the unfinished documents are counted in RUN_SUMMARY.pending. These stops write no status row; the outcome is in RUN_SUMMARY and the status message.
  • Each document that cannot be delivered writes one free status row ("recordType": "status"): NOT_AN_EINVOICE, NOT_FOUND, ACCESS_DENIED, CORRUPT_FILE, UNSUPPORTED_FILE, EMPTY_FILE, TOO_LARGE, BLOCKED_URL, BLOCKED (the URL answered with a challenge or captcha page instead of a file), FETCH_FAILED, DUPLICATE, INVALID_INPUT (an unreadable reference) or ERROR. Input that cannot be read at all (no documents, a wrong type) writes one free INVALID_INPUT status row and ends with an INVALID_INPUT status message.

⚡ Try the example

This actor has no free preview; the example below costs $0.01.

Open the actor's input page, switch to JSON, paste this and start the run:

{
"documents": ["sample:facturx", "sample:xrechnung"]
}

The two built-in fictitious samples are a Factur-X hybrid PDF and an XRechnung 3.0 UBL file; replace them with your own URLs or kv://STORE/KEY references, and set "includeLineItems": false for header fields at the lower price.

⚙️ Input

ParameterTypeDefaultDescription
documentsarray— (prefill the two samples)Up to 500 per run. Each is an http(s) URL to an .xml or hybrid .pdf, a key-value store record (kv://STORE_ID_OR_NAME/KEY or {"keyValueStoreId": "…", "key": "…"}), or sample:facturx / sample:xrechnung. A reference listed twice is read once; the same file under two references is delivered and charged once, and the repeat gets a free DUPLICATE row.
includeLineItemsbooleantrueReturn every invoice line. Rows with line items are charged as document-detail; turn this off for header fields only, charged as document.
feedbackstring—Optional note for the maintainers. It is logged and read by a human, and it never changes output.

🧱 Stable fields

These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.

FieldTypeMeaning
documentKindstring, optionalinvoice, credit_note, debit_note, corrected_invoice, prepayment_invoice, self_billed_invoice, partial_invoice and other EN 16931 type codes.
documentNumberstring, optionalThe invoice number.
issueDate / dueDatestring, optionalISO dates.
vendorName / vendorAddress / vendorVatIdstring, optionalSeller (legal registration name preferred), postal address and VAT ID.
buyerName / buyerVatIdstring, optionalBuyer and buyer VAT ID.
buyerReference / orderReferencestring, optionalBuyer reference (Leitweg-ID for German public buyers) and purchase order number.
iban / paymentTermsstring, optionalPayee account and payment terms text, as written.
currencystring, optionalInvoice currency code.
subtotal / taxTotal / totalnumber, optionalNet, tax and gross totals.
taxRatenumber, optionalThe single tax rate; omitted when several rates apply.
amountDuenumber, optionalPayable amount when it differs from total (prepayments).
lineItemsarray, optional{description, quantity, unit, unitPrice, amount, taxRate} per line, net amounts, in the XML's order; absent with includeLineItems: false.
statusstringData rows: complete (number, issue date, seller, total and currency present, all checks pass), partial (one of those missing) or inconsistent (see warnings). Status rows: the outcome code.
warningsarray, optionalPlain-language reasons for inconsistent.
checksobjecttotalsReconciled, lineItemsReconciled (when lines exist) and, for hybrid PDFs, xmlTotalInPdfText, xmlSubtotalInPdfText, xmlTaxInPdfText, xmlBreakdownInPdfText and printedTextReadable.
einvoiceobject{syntax: "CII" | "UBL" | "ZUGFeRD 1.0 (CII)", profile, file, container: "xml" | "pdf"}.
sourceobject{input, type: "url" | "kv" | "sample", sha256, bytes}.
evidenceobjectFor each field, the XML element it came from.
document / reasonstringStatus rows only: the reference as given, and why it was not delivered.
recordTypestring"status" on free status rows; "document" on data rows.

Other fields are extras, not part of the contract. To have one pinned, say so in feedback.

📦 Output example

Abridged real row from run TptAKSTt91t9Lo4aL on 2026-10-22 (the built-in fictitious sample:xrechnung); values are a historical snapshot.

{
"recordType": "document",
"documentKind": "invoice",
"documentNumber": "NW-2026-118",
"issueDate": "2026-10-01",
"dueDate": "2026-10-31",
"currency": "EUR",
"vendorName": "Nordlicht Werkstatt GmbH",
"vendorAddress": "Hafenweg 3, 20457 Hamburg, DE",
"vendorVatId": "DE111111111",
"buyerName": "Stadtverwaltung Beispielstadt",
"buyerReference": "04011000-12345-34",
"iban": "DE11111111111111111111",
"paymentTerms": "Zahlbar innerhalb 30 Tagen netto",
"subtotal": 700,
"taxTotal": 133,
"taxRate": 19,
"total": 833,
"lineItems": [
{"description": "Wartung Heizungsanlage", "quantity": 8, "unit": "HUR", "unitPrice": 70, "amount": 560, "taxRate": 19},
{"description": "Dichtungssatz", "quantity": 2, "unit": "C62", "unitPrice": 70, "amount": 140, "taxRate": 19}
],
"status": "complete",
"checks": {"lineItemsReconciled": true, "totalsReconciled": true},
"einvoice": {"syntax": "UBL", "profile": "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0", "file": "xml", "container": "xml"},
"evidence": {"documentNumber": "xml: cbc:ID", "vendorVatId": "xml: AccountingSupplierParty/Party/PartyTaxScheme", "total": "xml: LegalMonetaryTotal/TaxInclusiveAmount"},
"source": {"input": "sample:xrechnung", "type": "sample", "sha256": "c4bcb00dbf930141bb6fa8640f44292df12aebf958f81e313de23d80b794141d", "bytes": 3670}
}

A free status row looks like this (a plain PDF, run uXFS809QIF2nXRqr6, 2026-10-18):

{"recordType": "status", "document": "https://raw.githubusercontent.com/invoice-x/invoice2data/4feaeee60db51f1f12901efbac3396bb975c4852/tests/compare/coolblue1.pdf", "status": "NOT_AN_EINVOICE", "reason": "a PDF without embedded e-invoice XML (Factur-X / ZUGFeRD / XRechnung); v1 does not read plain PDFs"}

The run's status message reads like COMPLETE: 2 e-invoice(s) parsed (2 with line items)., and the RUN_SUMMARY record of its key-value store holds status, documents, withLineItems, charged, byStatus, pending and perDocument.

🧠 Advanced usage

Parse an accounts-payable inbox of e-invoice attachments

Save incoming attachments to a key-value store, pass them as kv://inbox/<key>, post rows with status: "complete" to your ledger and route inconsistent or partial rows to a person. The same file sent twice is charged once and comes back as a free DUPLICATE row.

Three-way match e-invoices against purchase orders

Join orderReference to your purchase orders and compare lineItems quantities and unitPrice against the order; buyerReference carries the Leitweg-ID on German public-sector invoices.

Check VAT IDs and bank details before paying

vendorVatId, buyerVatId and iban come straight from the XML, ready for a VIES lookup or a check against your supplier master data.

Know whether a run finished

Read RUN_SUMMARY.status: COMPLETE, PARTIAL (status rows, inconsistent invoices or pending documents), NO_RESULTS, BUDGET_LIMIT, TIME_LIMIT, ABORTED, STATE_SAVE_FAILED, PUSH_FAILED or INVALID_INPUT. If the actor's own pricing is misconfigured the run fails with PRICING_MISMATCH before reading anything, and nothing is charged. pending counts documents not yet processed.

🔌 Integrations

Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. Inputs are explicit file references and a new run parses and charges them again, so start one run per batch of new files from Make, Zapier, n8n or the API rather than re-running a fixed list. Copy-paste code in Python, Node, curl and n8n: architek-earth/examples/docparser-invoice-json.

💸 Pricing

Pay per result. Platform and proxy usage are included. Status rows and failed requests are free. A run that migrates or is resurrected after an abort continues from the PROGRESS record in its own key-value store: documents already delivered are skipped and not charged again. A new run does not share that record and parses its input from the start.

EventPriceWhat it covers
document$2.00 / 1,000 invoicesOne delivered e-invoice row without line items.
document-detail$5.00 / 1,000 invoicesOne delivered e-invoice row with its line items from the XML.

1,000 invoices with line items cost $5.00; header fields only cost $2.00. Each invoice is charged once, as one event or the other, and an invoice whose XML has no lines is charged as document.

❓ FAQ

Is there an XRechnung or ZUGFeRD API that returns JSON? This actor is one: send XRechnung, ZUGFeRD, Factur-X or PEPPOL UBL files through the Apify API and get JSON rows back, from any language or from n8n, Make and Zapier.

Do I need an account with an e-invoicing portal or a login? No. It reads the files you give it. A URL that needs a login or a signed link gets a free ACCESS_DENIED status row; put such files in a key-value store instead.

Can it read ordinary PDF invoices or scanned invoices? No. Only PDFs with embedded e-invoice XML (ZUGFeRD, Factur-X) and standalone XML are read; anything else gets a free NOT_AN_EINVOICE row.

Does it validate XRechnung against the KoSIT schematron? No. It reads the data and checks that totals and lines reconcile; it is not a legal validator.

Does it support PEPPOL BIS 3 and UBL credit notes? Yes. UBL 2.1 invoices and credit notes, including PEPPOL BIS 3 and XRechnung UBL, return documentKind credit_note where the XML says so.

What happens when the printed PDF and its XML disagree? You get the XML values with checks.xmlTotalInPdfText: false, status: "inconsistent" and a warning. For a ZUGFeRD or Factur-X hybrid the XML is the machine-readable invoice; ask the sender before paying.

🤖 For AI agents & LLM apps

Paste this into your AI assistant:

architekture/docparser-invoice-json on Apify. Python: from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/docparser-invoice-json").call(run_input={"documents": ["sample:facturx", "sample:xrechnung"], "includeLineItems": True}); items = client.dataset(run["defaultDatasetId"]).list_items().items (page with offset/limit for large exports). Rows with recordType == "document" are invoices; rows with recordType == "status" are free and say why a file was not delivered (status, reason). Use status (complete, partial, inconsistent) and warnings to decide when to hand an invoice to a person. Full input schema and README: GET https://api.apify.com/v2/acts/architekture~docparser-invoice-json/builds/default. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server (mcp.apify.com). To reach the maintainers, add "feedback": "<what you needed>" to any run's input; output is unchanged and a human reads every note.

🧰 More from architek.earth

Documents

  • EU E-Invoice Parser — you are here

Video, social and newsletters

Full catalogue: github.com/architek-earth.

architek.earth · code like concrete

Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.

This actor reads only the files you give it (URLs, key-value store records or the built-in samples) and processes them inside your Apify run. It does not bypass authentication. Invoices contain business and sometimes personal data such as names, addresses and bank accounts; you are responsible for a lawful basis to process them, for retention, and for privacy law such as GDPR where it applies. It extracts data and is not a legal e-invoice validator; this page is not legal or tax advice. Not affiliated with FeRD, AWV, KoSIT, FNFE-MPE or OpenPeppol.

📝 Changelog

  • 2026-10-22 — Runs on the studio core (architek_core 1.0.1): URL downloads use one Chrome browser identity, a challenge page is reported as a free BLOCKED status row, unreadable input writes a free INVALID_INPUT status row, and a run whose last invoice spends your limit exactly ends COMPLETE. Fields and prices unchanged.
  • 2026-10-22 — Status message now reads Done: N rows, M details, K status rows (STATUS).
  • 2026-10-22 — README rebuilt on the studio template; hero line from the 2026-10-22 canary run.
  • 2026-10-18 — 1.0: XRechnung (UBL and CII), ZUGFeRD 1.0 and 2.x, Factur-X and PEPPOL BIS 3, as XML or hybrid PDF; reconciliation checks and the printed-vs-XML total check; line items; free status rows; duplicate-file detection; clean stops at the spending limit and timeout; resumable after a platform migration.