Starting September 2026 every B2B invoice in France must be e-invoiced (Peppol/Factur-X). Germany has mandated XRechnung for B2G since 2020. Italy has been on FatturaPA since 2019. Spain's Verifactu rolls out 2025-2026.
If you build accounting software, an ERP, or any e-commerce flow that touches EU customers, you'll likely need to validate these invoice formats at some point. The two main open-source Schematron engines are phive (by Philip Helger of the EN16931 working group) and Mustang (by Jochen StΓ€rk and the FNFE-MPE working group). Both are great. Both ship as Java JARs or web forms β no API, no SDKs.
I built a thin REST API on top of Mustang 2.23.0 that gives you what's missing: SDKs, GitHub Action, and async batch.
The 5-line version
# pip install eleata-peppol
from eleata_peppol import Client
client = Client(api_key=os.environ["ELEATA_KEY"])
result = client.validate(format="peppol-bis-3", xml=open("invoice.xml", "rb").read())
print(result.valid, result.errors)
That's it. Same Schematron rules CEN/OpenPeppol publish β equivalent accuracy to the phive reference web form.
Node version
import { Eleata } from "@eleata/peppol";
import fs from "node:fs";
const client = new Eleata({ apiKey: process.env.ELEATA_KEY! });
const result = await client.validate({
format: "xrechnung-2.x",
xml: fs.readFileSync("./invoice.xml"),
});
if (!result.valid) console.error(result.errors);
In CI (GitHub Action)
- uses: eleata/validate-xrechnung-action@v1
with:
files: ./invoices/**/*.xml
api-key: ${{ secrets.ELEATA_KEY }}
Add a validates-in-CI badge to your README. Break the build before you ship a broken invoice.
What's in the box
- POST /v1/validate (sync) and /v1/validate/batch (async + webhook callback)
- 4 formats: Peppol BIS 3, XRechnung 2.x, Factur-X 1.07.2 (PDF/A-3 hybrid extracted natively), UBL 2.1
- Public shareable validation reports at /r/{id}
- 50 anonymized real EU invoice fixtures (CC0)
- Free 200 validations/month, no credit card
Honest about scope
This is not a full Peppol Access Point β Ecosio, B2BRouter, Pagero do that. We are only the validator-as-an-API layer. If you need to send invoices through the Peppol network, you still need an Access Point.
Repos public on github.com/eleata. Live demo at peppol.eleata.io.
Curious to hear from anyone using a different validator (xrechnung-tooling, validator-fhir, InvoiceNavigator). What pain points hit you first when integrating?
Top comments (0)