API · XRechnung · ZUGFeRD · EN 16931
E-invoice validation API
Send an XML e-invoice or a ZUGFeRD / Factur-X PDF and get back whether it conforms to the official rule sets, with every error and warning and its rule id. The checks run on the KoSIT validator with the XRechnung configuration, the EN 16931 validation artefacts and veraPDF. Technical validation, not tax advice.
Example request and response
An XRechnung 3.0 invoice without the buyer reference (BT-10). An invalid invoice is a normal result: the status is 200 and valid is false. A PDF goes the same way with Content-Type: application/pdf; any file can also be sent as the multipart field file or base64-encoded as JSON content_base64.
curl "https://api.vatcheckapi.com/v2/einvoice/validate?language=en" \
-H "apikey: YOUR-API-KEY" \
-H "Content-Type: application/xml" \
--data-binary @invoice.xml
{
"valid": false,
"format": "xrechnung",
"syntax": "UBL",
"profile": "XRECHNUNG",
"version": "3.0",
"container": "xml",
"specification_identifier": "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0",
"scenario": "EN16931 XRechnung (UBL Invoice)",
"ruleset_version": "xrechnung-3.0.2+cfg-2026-08-31;en16931-1.3.16;xrechnung-schematron-2.6.0;kosit-1.6.3;verapdf-1.30.2",
"pdfa": null,
"errors": [
{
"rule_id": "BR-DE-15",
"severity": "error",
"message": "Das Element \"Buyer reference\" (BT-10) muss übermittelt werden.",
"message_language": "de",
"source": "business_rules",
"location": "/ubl:Invoice[1]",
"line": null,
"column": null
}
],
"warnings": [
{
"rule_id": "BR-DE-TMP-32",
"severity": "information",
"message": "Eine Rechnung sollte zur Angabe des Liefer-/Leistungsdatums entweder BT-72 \"Actual delivery date\", BG-14 \"Invoicing period\" oder in jeder Rechnungsposition BG-26 \"Invoice line period\" enthalten.",
"message_language": "de",
"source": "business_rules",
"location": "/ubl:Invoice[1]",
"line": null,
"column": null
}
],
"summary": {
"invoice_number": "123456XX",
"issue_date": "2016-04-04",
"type_code": "380",
"currency": "EUR",
"seller": { "name": "[Seller name]", "vat_id": "DE 123456789" },
"buyer": { "name": "[Buyer name]" },
"totals": { "net_amount": "314.86", "tax_amount": "22.04", "gross_amount": "336.9", "payable_amount": "336.9" }
},
"language": "en",
"disclaimer": "Technical validation against the rule sets listed in ruleset_version. It is not tax or legal advice."
}
Response fields
- valid
truewhen the rule sets accepted the invoice and no check reported an error; for a PDF, PDF/A conformance is required too. Warnings do not make an invoice invalid.- format, syntax, profile, version
- What the file declares:
xrechnung,zugferd,en16931orpeppol-bis; UBL or CII; the profile (e.g. XRECHNUNG, EN 16931, BASIC) and version. - container
xmlorpdf: what you sent.- specification_identifier, scenario
- The specification identifier (BT-24) as declared, and the rule set scenario that was applied.
- ruleset_version
- The pinned versions of the rule sets and engines that ran, so a result can be traced later.
- pdfa
- For a PDF: whether it is PDF/A compliant and the profile checked (e.g. PDF/A-3B).
nullfor XML. - errors, warnings
- Each finding with
rule_id(e.g. BR-DE-15, BR-CO-10, a schema rule or a PDF/A clause),severity,message,message_language,source(input, xml, schema, business_rules, container, pdfa),location(XPath),lineandcolumn. - summary
- Invoice number, issue date, type code, currency, seller name and VAT ID, buyer name and the totals, as written in the invoice.
- language, disclaimer
- The language of the API's own messages (
enorde) and the note that this is technical validation, not tax or legal advice.
Use cases
Check incoming invoices
Validate supplier invoices before they reach accounts payable, and send the list of errors back to the supplier.
Test what your software sends
Run every XRechnung or ZUGFeRD invoice your billing system or ERP creates through the API before it goes out, in CI or at runtime.
Invoices to German public authorities
XRechnung for public buyers must carry the buyer reference (Leitweg-ID, BT-10). The national rules such as BR-DE-15 report it when it is missing.
AI agents and MCP
The MCP server offers the tool validateEinvoice: the agent sends the file base64-encoded and gets the same result.
Supported formats
| Format | Syntax | Checks |
|---|---|---|
| XRechnung 3.0, also Extension and CVD | UBL (Invoice, CreditNote), CII | XML, schema, EN 16931 and XRechnung rules |
| EN 16931 | UBL (Invoice, CreditNote), CII | XML, schema, EN 16931 rules |
| ZUGFeRD / Factur-X PDF, profile EN 16931 (COMFORT) or XRECHNUNG | CII embedded in a PDF | The checks above for the embedded XML, plus PDF/A-3 and the embedded file |
Recognised but not validated, answered with UNSUPPORTED_PROFILE at no cost: ZUGFeRD / Factur-X MINIMUM, BASIC WL, BASIC, EXTENDED and EXTENDED-CTC-FR, ZUGFeRD 1.0, XRechnung versions other than 3.0, the XRechnung 3.0 Extension credit note in UBL, and Peppol BIS. Format, syntax, profile and version are detected from the file, not from the file name.
Three ways to send the file
- Raw body:
Content-Type: application/xml(ortext/xml) for XML,application/pdffor a PDF. - Upload:
multipart/form-datawith the fieldfile. - JSON:
{"content_base64": "...", "filename": "invoice.pdf"}, for clients that can only send JSON, such as the MCP tool.
The optional format parameter (xrechnung, zugferd, en16931) asks whether the file is that format: if it declares another one, the result gets the error FORMAT_MISMATCH.
Costs
| Result | Requests counted |
|---|---|
An XML file that was validated, or that is not well-formed, not an e-invoice or has no specification identifier (BR-01) | 1 |
| A ZUGFeRD / Factur-X PDF whose invoice was validated (XML rules and PDF/A) | 2 |
A PDF without readable invoice XML (NO_EINVOICE_XML, PDF_UNREADABLE, PDF_ENCRYPTED, PDF_TOO_COMPLEX), or whose embedded XML is not well-formed or not an invoice | 1 |
UNSUPPORTED_PROFILE, EMBEDDED_XML_TOO_LARGE, INVOICE_TOO_COMPLEX | 0 |
| Sandbox keys | 0 |
Requests answered with 422, 403, 429 or 503 are not counted. The X-Cost header states the cost of each call. Before any work the API checks that your remaining quota can pay for the request (1 for XML, 2 for a PDF).
Privacy
Invoices are processed transiently and never persisted: the API keeps no copy of the file, writes none of its content to logs, and does not store the result.
Rule sets and licences
The validation runs on these open-source projects, unmodified. ruleset_version in each response names the exact versions.
- KoSIT validator and the XRechnung validator configuration with the XRechnung schematron rules, by KoSIT, Apache License 2.0.
- EN 16931 validation artefacts by CEN and the European Commission, European Union Public Licence (EUPL) 1.2.
- veraPDF for PDF/A conformance, Mozilla Public License 2.0.
The result is a technical validation against these rule sets. It is not tax or legal advice.
Start on the free plan
The free plan includes 150 requests a month. An XML invoice counts as 1 request, a ZUGFeRD / Factur-X PDF as 2. Recognised profiles that are not validated (UNSUPPORTED_PROFILE), embedded XML over 10 MB and invoices over the complexity limits count 0, and errors such as 422 or 503 are not counted.
Frequently asked questions
Which e-invoice formats does the API validate?
UNSUPPORTED_PROFILE and counts nothing.What exactly is checked?
Is the result tax advice?
ruleset_version. It does not check whether the invoice is right for the transaction behind it, and it is not tax or legal advice.Do you store the invoices?
Why are some messages in German?
message_language. The parameter language=de or en switches the API's own messages and the disclaimer.How large can an invoice be?
INVOICE_TOO_COMPLEX, not counted).Can I test it without using my quota?
SANDBOX-INVALID returns the error BR-DE-15.