Validate e-invoices against your own XSD or Schematron
Check e-invoices against the rules you maintain yourself: a CIUS, an extension or your organisation's internal rules. Upload your XSD, your ISO Schematron or both, and optionally run the built-in Peppol and EN 16931 checks in the same pass.
XML files
Up to 20 files · 5 MB each
The files to check. Each one is checked against all of your schema files.
Your XSD
Up to 50 files · 5 MB together
XSD 1.0. Add the main schema and every file it includes or imports; drop the folder to keep their paths.
Your Schematron
64 KB · 50 checks · 20 includes
One ISO Schematron file with queryBinding="xslt2" or "xslt3", at most 50 assert and report checks.
Add an XML file, and your XSD or Schematron.
No files at hand? : a Peppol invoice with a Schematron of in-house rules.
What it is for
The main validator picks the rule sets itself from the file. This page runs the rules you bring:
- A CIUS or national profile with its own Schematron that is not among the built-in schemas.
- In-house rules on top of Peppol BIS: a purchase order number, a payee IBAN, a fixed currency. Tick the built-in checks to get both in one result.
- Writing a Schematron: see which asserts fire on your test files, and XSD errors with their line and column.
The result page is the same as for the built-in checks, with a shareable link. It names your files (“Your XSD: invoice.xsd”, “Your Schematron: cius-rules.sch”) and claims Peppol or EN 16931 compliance only when the built-in checks ran.
What is supported
- XSD
- XSD 1.0, checked with libxml2. The main schema and every file it reaches by xs:include, xs:import, xs:redefine or xs:override, by a relative schemaLocation.
- Schematron
- ISO Schematron with
queryBinding="xslt2"or"xslt3"(XPath 3.1), compiled with the ISO skeleton and run by SaxonJS. sch:include, sch:extends, abstract patterns and sch:let work. The severity comes from flag or role: fatal or error, warning, info. - Not supported
- Schematron 1.5, the XSLT 1.0 binding; in a Schematron xsl:import, xsl:include, xsl:evaluate, fn:transform, text value templates (expand-text), static parameters and shadow attributes; XSD 1.1, DTD and RELAX NG.
- Network
- None. A schemaLocation or href that is a URL or an absolute path is rejected: nothing is downloaded, so upload what your schema imports.
- Order of checks
- Not well-formed XML stops at the parse errors. Then your XSD (and the built-in one, if ticked), then your Schematron and the built-in rule sets.
Limits
- XML files
- Up to 20 per validation, 5 MB each
- XSD
- Up to 50 files, 5 MB together
- Schematron
- One file plus up to 20 include files, 64 KB together
- Schematron checks
- Up to 50 sch:assert and sch:report, counted after includes and abstract patterns are expanded
- Schematron size
- Up to 50 sch:let and 16 namespaces, and at most 48 KB of generated XSLT: about 50 checks with short messages
- File names
- Letters A-Z, digits, dot, underscore, hyphen and / for folders
- Kept
- 7 days after the upload
Your files are checked before anything is stored. Compiling a Schematron takes a few seconds, and each XML file takes a few seconds more.
Storage
Your XSD and Schematron are kept for 7 days, stored by the SHA-256 hash of their contents: the XSD files as uploaded, the Schematron as the XSLT it compiles to. Uploading the same files again within 6 days skips the compile step. After the 7 days, an unfinished result asks you to upload them again. XML files are stored like any other validation: see the privacy policy.
API and MCP
POST /api/v1/validate takes the same files as multipart fields next to file: xsd (repeat it for every schema file), xsdMain (needed with more than one XSD), schematron, schematronInclude (repeat) and builtin=true. A file name may contain folders: curl sends only the base name unless you set filename=.
curl -X POST https://peppolvalidator.com/api/v1/validate \
-F "file=@invoice.xml" \
-F "xsd=@invoice.xsd" \
-F "xsd=@common/types.xsd;filename=common/types.xsd" \
-F "xsdMain=invoice.xsd" \
-F "schematron=@cius-rules.sch" \
-F "builtin=true"The result lists your files under custom, and the issues from them have custom: true: XSD issues with type: "xsd", line and column, Schematron issues with type: "schematron". Without builtin, ruleSets is empty.
"custom": {
"xsd": { "main": "invoice.xsd", "files": ["common/types.xsd", "invoice.xsd"], "hash": "…" },
"schematron": { "filename": "cius-rules.sch", "includes": [], "queryBinding": "xslt2", "hash": "…" },
"builtin": true
}A problem with your files is a 400 with error, code and details (file, line, the compiler's message):
| Code | Meaning |
|---|---|
| XSD_INCLUDE_MISSING, SCHEMATRON_INCLUDE_MISSING | A schemaLocation or href names a file you did not upload |
| XSD_REMOTE_LOCATION, SCHEMATRON_REMOTE_LOCATION | A URL or an absolute path: nothing is downloaded |
| XSD_MAIN_MISSING | Several XSD files and no xsdMain |
| XSD_INVALID, SCHEMATRON_INVALID | Not well-formed, not xs:schema, or not ISO Schematron |
| SCHEMATRON_QUERY_BINDING | No queryBinding (XSLT 1.0) or one other than xslt2 / xslt3 |
| SCHEMATRON_UNSUPPORTED | xsl:import, xsl:include, xsl:evaluate, fn:transform, function-lookup, text value templates, static parameters, shadow attributes or SaxonJS extensions |
| XSD_COMPILE_FAILED, SCHEMATRON_COMPILE_FAILED | The compiler's messages, with the file and line |
| …_TOO_LARGE, …_TOO_MANY_FILES, SCHEMATRON_TOO_COMPLEX | Over a limit above |
The MCP server tool validate_invoice takes the files as text: xsd (file name to XSD text), xsdMain, schematron, schematronIncludes (file name to text) and builtin. See the API docs.
FAQ
Can I check an invoice against a CIUS this validator has no rule set for?
Yes. Upload the CIUS Schematron (and its XSD, if it has one) together with the invoice. Tick the built-in checks to run EN 16931 and Peppol BIS or XRechnung in the same run; the result then lists the built-in issues and those of your files side by side.
Does the result say my invoice is Peppol compliant?
Only when the built-in checks ran and passed. With your own files alone the result says the file passed your XSD and your Schematron, and names them; it makes no claim about Peppol or EN 16931.
Why is my Schematron rejected with SCHEMATRON_QUERY_BINDING?
Your schema has no queryBinding (which means XSLT 1.0) or one other than xslt2 or xslt3. Set queryBinding="xslt2" on the sch:schema element. Most XSLT 1.0 tests run unchanged as XPath 2.0.
My XSD includes common/types.xsd. How do I upload it?
Drop the folder with your schemas: the files keep their paths. You can also pick the files one by one; a file picked on its own is sent under the path another file refers to it by, when no other file has that name. Over the API, give the path as the file name, e.g. curl -F "xsd=@common/types.xsd;filename=common/types.xsd".
Can my schema import the UBL or xmldsig schemas from the web?
No. The validator never downloads anything: a schemaLocation or href that is a URL or an absolute path is rejected. Upload the schemas you import and refer to them by a relative path.
How long are my XSD and Schematron kept?
7 days after the upload that stored them, under the SHA-256 hash of their contents. Uploading the same files again within 6 days reuses them and skips the compile step; after that they are compiled again and kept for another 7 days.
Only need the built-in checks? Go to the Peppol validator