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
true when 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, en16931 or peppol-bis; UBL or CII; the profile (e.g. XRECHNUNG, EN 16931, BASIC) and version.
container
xml or pdf: 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). null for 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), line and column.
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 (en or de) 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

FormatSyntaxChecks
XRechnung 3.0, also Extension and CVDUBL (Invoice, CreditNote), CIIXML, schema, EN 16931 and XRechnung rules
EN 16931UBL (Invoice, CreditNote), CIIXML, schema, EN 16931 rules
ZUGFeRD / Factur-X PDF, profile EN 16931 (COMFORT) or XRECHNUNGCII embedded in a PDFThe 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 (or text/xml) for XML, application/pdf for a PDF.
  • Upload: multipart/form-data with the field file.
  • 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

ResultRequests 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 invoice1
UNSUPPORTED_PROFILE, EMBEDDED_XML_TOO_LARGE, INVOICE_TOO_COMPLEX0
Sandbox keys0

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.

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?

XRechnung 3.0 in UBL and CII syntax (also the CVD and Extension specifications, except the Extension as a UBL credit note), EN 16931 invoices in UBL and CII, and ZUGFeRD / Factur-X PDFs with the profile EN 16931 (COMFORT) or XRECHNUNG. ZUGFeRD / Factur-X MINIMUM, BASIC WL, BASIC, EXTENDED and EXTENDED-CTC-FR, ZUGFeRD 1.0, other XRechnung versions, the XRechnung 3.0 Extension credit note in UBL and Peppol BIS are recognised but not validated yet; the API reports UNSUPPORTED_PROFILE and counts nothing.

What exactly is checked?

XML well-formedness, the XML schema, the EN 16931 business rules and the national XRechnung rules. For a ZUGFeRD / Factur-X PDF also PDF/A-3 conformance and the embedded invoice file: its name, AFRelationship, MIME type, association with the document and the XMP metadata.

Is the result tax advice?

No. The API checks whether the file conforms to the rule sets named in 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?

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

Why are some messages in German?

Rule set messages keep the language their rule set is published in: the XRechnung rules (BR-DE-*) are German, the EN 16931 rules, schema messages and PDF/A rules English. Each finding has message_language. The parameter language=de or en switches the API's own messages and the disclaimer.

How large can an invoice be?

At most 10 MB per file, which also applies to the invoice XML inside a PDF. Invoices with more than 50 VAT breakdowns or more than 1,000 document level allowances and charges are not validated (INVOICE_TOO_COMPLEX, not counted).

Can I test it without using my quota?

Yes. With a sandbox API key the API reads the file, detects the format and extracts the summary, but returns a fixed rule set result at no cost. The invoice number SANDBOX-INVALID returns the error BR-DE-15.

Related

Free VAT and EORI tools

Start using our VAT Validation API for free today!

Get 150 validations / month for free