ZUGFeRD & Factur-X PDF to JSON - Invoice Parser & Extractor
Pricing
from $5.00 / 1,000 document processeds
ZUGFeRD & Factur-X PDF to JSON - Invoice Parser & Extractor
Extract embedded invoice XML from hybrid PDF/A-3 files, normalize EN 16931 data, and return a versioned technical conformance report. E-invoice parser and data extraction for ZUGFeRD and Factur-X: every parsed field ships with validation findings, never silent guesses.
Pricing
from $5.00 / 1,000 document processeds
Rating
0.0
(0)
Developer
Kamer Ozkan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
Turn ZUGFeRD and Factur-X hybrid PDF invoices into clean JSON. This invoice parser extracts the embedded CII XML from each PDF/A-3 file, normalizes the EN 16931 business terms (seller, buyer, lines, VAT, totals, payment) and returns one stable JSON record per invoice, together with a technical conformance report. No OCR and no guessing: every value comes from the XML the sender embedded.
What it does
- Accepts up to 20 hybrid PDFs per run and 20 MiB per PDF.
- Reads uploads, inline base64, public or signed HTTPS URLs, and key-value store records.
- Extracts exactly one recognized invoice attachment per PDF in an isolated worker.
- Checks PDF/A-3 identification, XMP metadata, attachment name,
AFRelationship, MIME type, stream digest and profile consistency. - Validates MINIMUM, BASIC WL, BASIC, EN16931 and EXTENDED profile XML with release-pinned ZUGFeRD 2.5 / Factur-X 1.09 rules.
- Validates ZUGFeRD 1.0 XML with pinned Mustangproject
2.24.0, then makes a digest-verified, fail-closed D16B upgrade attempt before JSON normalization. - Normalizes CII business terms into a shared JSON contract with EN 16931 trace entries and decimal strings (amounts are never floats).
- Optionally stores the extracted XML, validator XML and veraPDF reports in the run key-value store.
Who it is for
- Accounts payable and AP automation teams that receive ZUGFeRD or Factur-X invoices from German and French suppliers and want structured data instead of PDFs.
- ERP, accounting and expense software developers who need a ZUGFeRD parser or Factur-X extractor behind an API without maintaining Java validators.
- Invoice inbound gateways and service providers that must check whether a received PDF really is a conformant hybrid e-invoice before booking it.
- AI agents and automations (n8n, Make, Zapier, MCP) that read invoices.
Output: data you get
One Dataset row per submitted PDF.
| Field | What it contains |
|---|---|
itemId, fileName, inputIndex | Your document ID, file name and position in the input |
processingStatus | SUCCEEDED or FAILED |
conformanceStatus | ACCEPTED, REJECTED or NOT_EVALUATED |
billable | true only when the document was charged |
source.standard | Detected family (ZUGFeRD / Factur-X), profile, scenario and version |
source.sha256, source.embeddedXmlSha256 | Digests of the PDF and the embedded XML |
normalizationStatus | COMPLETE when every declared business term was transferred, otherwise PARTIAL |
invoice.document | Invoice number, type code, issue date, currency and notes |
invoice.parties | Seller and buyer (plus other parties when declared in the XML) |
invoice.lines | Invoice lines |
invoice.totals | Document totals |
invoice.paymentTerms, invoice.delivery | Payment terms and delivery information |
invoice.vatBreakdowns, invoice.documentAllowancesCharges | VAT breakdown and document-level allowances and charges |
invoice.paymentInstructions, invoice.references | Payment instructions and referenced documents |
invoice.trace, invoice.unmapped | EN 16931 trace entries and any term that could not be mapped |
report | Overall result (CONFORMANT, NON_CONFORMANT, INDETERMINATE) with PDF, XML and business rule findings |
artifacts | Keys and digests of stored XML and reports (when enabled) |
error | Error code and message for rejected inputs |
Sample output
Unedited record from a live run on 2026-07-30 against an official ZUGFeRD corpus PDF; long sub-objects are shortened here, values are exactly as returned:
{"contractVersion": "einvoice-suite-result/1.0.0","actorName": "zugferd-facturx-pdf-to-json","itemId": "corpus-zugferd-en16931","inputIndex": 0,"fileName": "zugferd_2p0_EN16931_Einfach.pdf","producedAt": "2026-07-30T08:40:44.866151Z","processingStatus": "SUCCEEDED","conformanceStatus": "ACCEPTED","billable": true,"scope": "DOCUMENT_EXTRACTION_NORMALIZATION_AND_TECHNICAL_CHECKS","source": {"sourceKind": "URL","container": "PDF_A_3","syntax": "CII_INVOICE","sha256": "29842457f57143aba5da78fdf390aba773c965e60b1caab93dfff3e9d4c802f4","embeddedXmlSha256": "5600027528d5ffaf89fb0be911c73ec84125a98411525e7299c7ca3a0ab073f7","standard": {"family": "ZUGFERD","profile": "ZUGFERD_EN16931","scenario": "ZUGFeRD 2.5 / Factur-X 1.09 EN16931","version": "2.x"}},"normalizationStatus": "PARTIAL","report": "(report, shortened here)","container": "(container, shortened here)","engineDurationMs": 6533,"artifacts": {"embeddedXml": {"mediaType": "application/xml","byteLength": 10702,"sha256": "5600027528d5ffaf89fb0be911c73ec84125a98411525e7299c7ca3a0ab073f7","storageStatus": "NOT_REQUESTED"}},"invoice": "(invoice, shortened here)"}
A plain PDF without embedded invoice XML is refused with a named error, and
billable: false means it is not charged. Unedited record from a live run on 2026-07-30:
{"contractVersion": "einvoice-suite-result/1.0.0","actorName": "zugferd-facturx-pdf-to-json","itemId": "plain-pdf","inputIndex": 0,"fileName": "plain.pdf","producedAt": "2026-07-30T08:52:37.059056Z","processingStatus": "FAILED","conformanceStatus": "NOT_EVALUATED","billable": false,"scope": "DOCUMENT_EXTRACTION_NORMALIZATION_AND_TECHNICAL_CHECKS","error": {"code": "PDF_PARSE_FAILED","message": "The input PDF could not be parsed safely"}}
Pricing
Pay per event, no subscription:
| Event | Price |
|---|---|
| Document processed (one PDF that completed the pipeline and produced a billable result) | $0.005 per document |
| Actor start | $0.00005 per GB of run memory |
Worked example: 200 supplier invoices in one run at 2 GB memory cost 200 x $0.005 = $1.00 for documents plus $0.0001 for the start, about $1.00 in total. That is $5 per 1,000 documents.
Not charged: source download failures, plain PDFs without invoice XML
(NOT_EVALUATED), runtime failures and documents skipped because your spending
limit was reached. The Actor respects the maximum cost per run you set in Apify.
How to use it
- Click Try for free and open the Input tab.
- Upload your hybrid PDFs under Upload invoice PDFs, or paste HTTPS links in API documents (the prefilled example uses an official ZUGFeRD corpus file).
- Optional: turn on Store extracted XML or Store technical reports if you need the raw XML or the veraPDF report for your archive.
- Click Start. Each PDF takes a few seconds; results appear in the Output tab.
- Download as JSON, CSV or Excel, or read the Dataset through the API.
Input
| Field | Description |
|---|---|
invoiceFiles | Uploaded PDF files (up to 20) |
documents | API sources, each with exactly one of url, base64 or keyValueStoreKey, plus optional documentId and fileName |
sourceKeyValueStoreId | Key-value store that holds records referenced by keyValueStoreKey |
allowPartialNormalization | Return safely parsed fields even for non-conformant documents (default true) |
storeEmbeddedXml | Store the complete embedded XML in the key-value store (default false) |
storeTechnicalReports | Store the rules report and veraPDF report (default false) |
maxFindingsPerDocument | Maximum findings returned per invoice, 1 to 500 (default 100) |
Input example:
{"documents": [{"documentId": "supplier-4711","fileName": "zugferd_2p0_EN16931_Einfach.pdf","url": "https://raw.githubusercontent.com/ZUGFeRD/corpus/master/ZUGFeRDv2/correct/intarsys/EN16931/zugferd_2p0_EN16931_Einfach.pdf"}],"allowPartialNormalization": true,"storeEmbeddedXml": false,"maxFindingsPerDocument": 20}
API and integrations
Run it from your own code with the Apify API and get the Dataset rows back in one call:
curl -X POST "https://api.apify.com/v2/acts/kamerozkan~zugferd-facturx-pdf-to-json/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"documents":[{"documentId":"inv-1","url":"https://example.com/invoice.pdf"}]}'
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("kamerozkan/zugferd-facturx-pdf-to-json").call(run_input={"documents": [{"documentId": "inv-1", "url": "https://example.com/invoice.pdf"}]})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["conformanceStatus"], row.get("invoice", {}).get("document"))
It also works with Make, n8n, Zapier and webhooks through the standard Apify integrations, and AI agents can find and run it through Apify's MCP server (mcp.apify.com) with the same pay-per-event billing.
FAQ
Which formats are supported? ZUGFeRD 1.0, ZUGFeRD 2.x and Factur-X 1.0x hybrid PDFs (PDF/A-3 with embedded CII XML), profiles MINIMUM, BASIC WL, BASIC, EN16931 and EXTENDED. Plain XRechnung or UBL XML files without a PDF belong to the parsers in the tool family below.
Does it read scanned or normal PDFs? No. A regular PDF without embedded invoice XML is rejected and not charged. OCR is not used to guess invoice values.
What does PARTIAL mean?
normalizationStatus is independent from technical conformance. It is COMPLETE only
when the full declared profile was transferred without unmapped evidence or converter
warnings. Reduced profiles (MINIMUM, BASIC WL) and unsupported extension semantics
return honest PARTIAL output, and the unmapped terms are listed.
How are ZUGFeRD 1.0 files handled?
The original XML is validated, then upgraded to D16B with a pinned, digest-verified
XSLT before normalization. Provenance is LEGACY_ZF1_VIA_PINNED_UPGRADE, both digests
are recorded, and the integrity boundary is reported as NOT_PROVEN_BY_UPGRADER.
Is this a legal validity check? No. It does not compare the visible PDF text with the XML and does not verify electronic signatures. The report is a technical assessment, not a tax or legal decision.
Is invoice data stored? Dataset rows contain metadata, hashes, report summaries and normalized JSON. Raw XML and technical reports are stored only when you turn the options on.
E-invoice tool family
Validators, one per market, same output discipline: XRechnung & ZUGFeRD | Peppol BIS | France | Poland KSeF | Italy FatturaPA
Support
Found a PDF that should work but does not? Open an issue in the Issues tab with the run ID (and, if you can share it, a test file). Issues are checked every day.