ZUGFeRD Validation API
The InvoiceXML ZUGFeRD validation API validates any ZUGFeRD PDF — from legacy version 1.0 through the latest 2.4 — against the official EN 16931 Schematron and PDF/A-3b conformance requirements. The same checks that determine whether DATEV, SAP, and German ERP systems accept or reject the file on import.
Drop your ZUGFeRD PDF here
or browse files to upload
POST /v1/validate/zugferd · Accepted format: PDF · All versions 1.0–2.4 · Max 20 MB
Validate ZUGFeRD REST API Request
A single API call handles ZUGFeRD 1.0 through 2.4 — version detection, XML extraction, and all validation layers run automatically:
$ curl -X POST https://api.invoicexml.com/v1/validate/zugferd \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "[email protected]"
Validate ZUGFeRD API Response
Both valid and invalid invoices return HTTP 200. The response includes the detected ZUGFeRD version and profile read directly from the embedded XML — so you know exactly which version was validated, not which version you assumed you were sending.
Validation errors are returned in two formats: raw Schematron rule codes for programmatic handling in your pipeline, and a friendly message array with plain-language descriptions you can render directly in a dashboard, notification, or no-code workflow step.
Valid ZUGFeRD Response
// 200 OK { "valid": true, "detail": "Your invoice is ZUGFeRD compliant and meets the EN 16931 specifications.", "data": { "schemaValid": true, "schematronValid": true, "conformanceLevel": "EN16931", "detectedVersion": "2.3.2", "specificationIdentifier": "urn:cen.eu:en16931:2017#conformant#urn..." } }
Invalid ZUGFeRD Response
// 200 OK { "valid": false, "detail": "Validation failed with 3 error(s)", "data": { "conformanceLevel": "EN16931", "detectedVersion": "2.3.2", "specificationIdentifier": "urn:cen.eu:en16931:2017#conformant#urn..." }, "errors": { "xml": [ "[BR-AE-05] In an invoice line where VAT category code is Reverse charge, the VAT rate shall be 0.", "[BR-AE-09] The VAT category tax amount in a VAT breakdown with category code Reverse charge shall be 0.", "[BR-CO-14] Invoice total VAT amount must equal the sum of VAT category tax amounts." ], "friendly": [ { "rule": "BR-AE-05", "line": 2, "message": "When using Reverse charge VAT, the VAT rate must be set to 0%." }, { "rule": "BR-AE-09", "message": "The total VAT amount for the Reverse charge breakdown must be 0." }, { "rule": "BR-CO-14", "message": "The invoice total VAT amount does not match the sum of VAT breakdown." } ] } }
What the ZUGFeRD validation API checks
Version Detection and XML Extraction
Extracts the embedded zugferd-invoice.xml attachment from the PDF/A-3 container and detects the ZUGFeRD version automatically. ZUGFeRD 1.0 (root element CrossIndustryDocument) and ZUGFeRD 2.x (root element CrossIndustryInvoice) use different namespace structures and different validation artefacts — the API routes each to the correct pipeline without any version parameter required.
CII XSD Schema
Validates the extracted CII XML against the UN/CEFACT CII D16B XSD schema. Catches malformed XML, missing required elements, incorrect data types, and namespace errors. For ZUGFeRD 1.0 files, the legacy CrossIndustryDocument schema is applied. For 2.x files, the current CrossIndustryInvoice D16B schema is used.
EN 16931 Schematron
Validates all 200+ EN 16931 business rules (BR-xx codes) against the embedded CII XML. Covers arithmetic rules (BR-CO-14: VAT totals must balance), VAT category rules (BR-AE-05: reverse charge rate must be zero), party rules (BR-01: specification identifier required), and payment rules. The profile declared in the specification identifier determines which rules are mandatory vs optional.
PDF/A-3b and ERP Import Conditions
Checks the outer PDF container for the conditions that DATEV, SAP, Lexware, and compatible German ERP systems verify on import: embedded fonts, ICC colour profile, XMP metadata with the correct ZUGFeRD namespace and version declaration, AFRelationship set to Alternative, and the embedded file named exactly zugferd-invoice.xml. A file that fails any of these is silently treated as a plain PDF on import — no error, no structured data.
Response schema
Both valid and invalid invoices return HTTP 200. The detectedVersion and specificationIdentifier fields confirm exactly which ZUGFeRD version was validated — useful when processing invoices from multiple suppliers who may be sending different versions. Create/convert endpoints return HTTP 400 with the same errors structure on validation failure.
| Field | Type | Description |
|---|---|---|
| Always present | ||
| valid | boolean | Primary flag to branch on. true when the file passes all CII, Schematron, and PDF/A-3b checks. |
| detail | string | Human-readable summary, e.g. "Your invoice is ZUGFeRD compliant…" or "Validation failed with 2 error(s)". |
| data.conformanceLevel | string | Detected EN 16931 profile, e.g. EN16931, EXTENDED, BASIC. |
| data.detectedVersion | string | ZUGFeRD version read from the embedded XML, e.g. 2.3.2, 2.1.1, 1.0. Not assumed from the filename — read from the actual specification identifier. |
| data.specificationIdentifier | string | Full specification identifier URI from the embedded XML, e.g. urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:en16931. |
| Valid only | ||
| data.schemaValid | boolean | CII XSD schema check passed for the detected version. |
| data.schematronValid | boolean | EN 16931 Schematron business rules check passed. |
| Invalid only | ||
| errors.xml | string[] | Raw Schematron messages with rule codes, e.g. "[BR-CO-14] Invoice total VAT amount must equal the sum of VAT breakdown amounts." |
| errors.friendly | object[] | Plain-language error objects for UI display. |
| friendly[].rule | string | Rule identifier, e.g. BR-AE-05, BR-CO-14. |
| friendly[].line | int? | Invoice line item number where the violation occurred, or null for document-level errors. |
| friendly[].message | string | Human-readable error description suitable for end users and no-code notification workflows. |
Integrate ZUGFeRD validation into your workflow
REST API
Call POST /v1/validate/zugferd from any language. Accepts ZUGFeRD 1.0 through 2.4 without a version parameter — detection is automatic. Returns structured JSON in under 2 seconds. Use valid to gate ERP import pipelines and detectedVersion to log which version your suppliers are sending.
API docsZapier / Make / n8n
Screen incoming ZUGFeRD invoices from suppliers before they reach your accounting system. Route non-compliant files to a Slack channel or email with the friendly errors[].message values so your team knows exactly what to ask the supplier to fix — before the file causes a silent DATEV import failure.
Automation integrationsCI/CD Pipeline
Validate ZUGFeRD output on every build of your invoice generation pipeline. When FeRD publishes a new version — ZUGFeRD 2.4 made service period dates mandatory and deprecated NIL elements — the API validation rules update automatically. Your pipeline catches regressions before non-compliant invoices reach your customers.
View cURL exampleComplete ZUGFeRD Toolkit
Everything you need to create, convert, validate, and extract ZUGFeRD invoices — via REST API or online.
Build a ZUGFeRD 2.x PDF/A-3 from structured data — no source PDF required.
Validate a ZUGFeRD PDF against EN 16931 XSD schema and Schematron business rules.
Convert any PDF invoice into a ZUGFeRD 2.x PDF/A-3 with embedded CII XML using AI extraction.
Extract the embedded CII XML from a ZUGFeRD PDF for ERP import or further processing.
Frequently Asked Questions
Which ZUGFeRD versions does the API validate?
The API validates all ZUGFeRD versions from 1.0 through 2.4 (Factur-X 1.08). The version is detected automatically from the embedded XML — ZUGFeRD 1.0 uses the CrossIndustryDocument root element and a different namespace structure, while ZUGFeRD 2.x uses CrossIndustryInvoice. Each version is validated against its own correct schema and Schematron artefacts.
Does validation check the PDF/A-3b container as well as the embedded XML?
Yes. The API runs a full PDF/A-3b conformance check on the outer PDF container — embedded fonts, ICC colour profile, XMP metadata block with the correct ZUGFeRD namespace, AFRelationship declaration, and the embedded XML filename (zugferd-invoice.xml). All of these must be correct for DATEV, SAP, and other German ERP systems to import the file without errors.
Why does my ZUGFeRD file pass the XML check but fail on import into DATEV or SAP?
DATEV and SAP perform import checks beyond EN 16931 Schematron validation. They verify the embedded filename is exactly zugferd-invoice.xml, that the AFRelationship attribute is set to Alternative, and that the XMP metadata block contains the correct ZUGFeRD version and profile declarations. The InvoiceXML validation API checks all of these layers — not just the XML — so failures that only surface on ERP import are caught before the file leaves your pipeline.