ZUGFeRD & Factur-X PDF to JSON - Invoice Parser & Extractor avatar

ZUGFeRD & Factur-X PDF to JSON - Invoice Parser & Extractor

Pricing

from $5.00 / 1,000 document processeds

Go to Apify Store
ZUGFeRD & Factur-X PDF to JSON - Invoice Parser & Extractor

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

Kamer Ozkan

Maintained by Community

Actor 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.

FieldWhat it contains
itemId, fileName, inputIndexYour document ID, file name and position in the input
processingStatusSUCCEEDED or FAILED
conformanceStatusACCEPTED, REJECTED or NOT_EVALUATED
billabletrue only when the document was charged
source.standardDetected family (ZUGFeRD / Factur-X), profile, scenario and version
source.sha256, source.embeddedXmlSha256Digests of the PDF and the embedded XML
normalizationStatusCOMPLETE when every declared business term was transferred, otherwise PARTIAL
invoice.documentInvoice number, type code, issue date, currency and notes
invoice.partiesSeller and buyer (plus other parties when declared in the XML)
invoice.linesInvoice lines
invoice.totalsDocument totals
invoice.paymentTerms, invoice.deliveryPayment terms and delivery information
invoice.vatBreakdowns, invoice.documentAllowancesChargesVAT breakdown and document-level allowances and charges
invoice.paymentInstructions, invoice.referencesPayment instructions and referenced documents
invoice.trace, invoice.unmappedEN 16931 trace entries and any term that could not be mapped
reportOverall result (CONFORMANT, NON_CONFORMANT, INDETERMINATE) with PDF, XML and business rule findings
artifactsKeys and digests of stored XML and reports (when enabled)
errorError 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:

EventPrice
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

  1. Click Try for free and open the Input tab.
  2. Upload your hybrid PDFs under Upload invoice PDFs, or paste HTTPS links in API documents (the prefilled example uses an official ZUGFeRD corpus file).
  3. Optional: turn on Store extracted XML or Store technical reports if you need the raw XML or the veraPDF report for your archive.
  4. Click Start. Each PDF takes a few seconds; results appear in the Output tab.
  5. Download as JSON, CSV or Excel, or read the Dataset through the API.

Input

FieldDescription
invoiceFilesUploaded PDF files (up to 20)
documentsAPI sources, each with exactly one of url, base64 or keyValueStoreKey, plus optional documentId and fileName
sourceKeyValueStoreIdKey-value store that holds records referenced by keyValueStoreKey
allowPartialNormalizationReturn safely parsed fields even for non-conformant documents (default true)
storeEmbeddedXmlStore the complete embedded XML in the key-value store (default false)
storeTechnicalReportsStore the rules report and veraPDF report (default false)
maxFindingsPerDocumentMaximum 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 ApifyClient
client = 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.