Eine ZUGFeRD-CLI validiert E-Rechnungen skriptbar über die Kommandozeile – lokal, in CI/CD oder per API-Aufruf, ohne Browser-Upload.
Dafür gibt es vier praktikable Wege, die sich in einem Punkt deutlich unterscheiden: ob eine Java-Laufzeitumgebung auf der Maschine liegen muss. Diese Seite zeigt alle vier mit lauffähigen Beispielen und ordnet ein, wann welcher sinnvoll ist.
Welche Optionen gibt es?
| Weg | Voraussetzungen | Offline-fähig | Ausgabeformat | Typischer Einsatz |
|---|---|---|---|---|
| curl + REST API | curl, base64 |
Nein | JSON | CI/CD, Skripte, schlanke Container |
| Mustang-CLI | Java ≥ 21, JAR-Download | Ja | XML-Report | Lokale Prüfung, Daten dürfen das Netz nicht verlassen |
| KoSIT-Validator | Java ≥ 11, JAR und XRechnung-Konfiguration | Ja | XML-Report, auf Wunsch HTML | XRechnung lokal gegen die KoSIT-Konfiguration prüfen |
| MCP-Client | Node.js ≥ 18 | Nein | JSON (MCP-Tools) | KI-Agenten in Cursor, Windsurf, Claude |
Kurz gefasst: curl ist der schnellste Weg in eine Pipeline. Mustang-CLI und KoSIT-Validator prüfen offline, Mustang auch ZUGFeRD-PDFs, KoSIT nur XML. Der MCP-Client ist der Weg, wenn ein KI-Agent die Prüfung selbst auslösen soll.
ZUGFeRD und XRechnung per curl validieren
Unsere REST API nimmt den Dateiinhalt base64-kodiert entgegen und antwortet mit strukturiertem JSON. Auf der Maschine muss dafür kein Java liegen: curl und ein Base64-Kommando reichen. Im Hintergrund prüft dieselbe Engine wie beim ZUGFeRD Validator im Browser: das Mustang Project und das KoSIT-Validierungstool gegen die Norm EN 16931 und die deutschen Geschäftsregeln (BR-DE).
Beispiel-Request
Die Datei wird zuerst base64-kodiert und dann als file_content übergeben. file_type ist xml für eine XRechnung oder CII-XML und pdf für ein ZUGFeRD- oder Factur-X-PDF. Der API-Key gehört in den X-Api-Key-Header.
# XRechnung-XML in einem Durchgang prüfen (macOS/Linux) B64=$(base64 < rechnung.xml | tr -d '\n') curl -X POST https://api.zugferd-validator.de/v1/validate \ -H "X-Api-Key: zv_demo_public_zugferd_2026" \ -H "Content-Type: application/json" \ -d "{\"file_content\":\"$B64\",\"file_type\":\"xml\"}"
Für ein ZUGFeRD-PDF ändert sich nur die Quelldatei und file_type — das eingebettete XML extrahiert der Validator selbst und erkennt auch das Profil (MINIMUM bis EXTENDED) automatisch:
# ZUGFeRD-PDF statt XML B64=$(base64 < rechnung.pdf | tr -d '\n') # … dieselbe Anfrage, aber: "file_type":"pdf"
zv_demo_public_zugferd_2026 funktioniert sofort ohne Anmeldung (1 Anfrage pro Tag und IP) — gut zum Ausprobieren, zu wenig für eine Pipeline. Ein kostenloser API-Key bringt 20 Validierungen pro Woche.Das JSON-Ergebnis lesen
Die Antwort ist bewusst maschinenlesbar, kein Freitext. valid trägt das Gesamtergebnis, errors und warnings listen jeden Punkt mit Regel-ID, betroffenem BT-Feld, Korrekturvorschlag und XPath:
{
"valid": false,
"format": "ZUGFeRD 2.4.0",
"profile": "EN16931",
"summary": "1 Fehler gefunden",
"errors": [{
"severity": "error",
"rule_id": "BR-DE-1",
"field": "BG-16",
"message": "PAYMENT INSTRUCTIONS (BG-16) fehlen.",
"fix_suggestion": "Füge die Gruppe BG-16 hinzu: mindestens die Zahlungsart ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode (BT-81).",
"xpath": "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans"
}]
}
Wichtig für die Auswertung: Warnungen allein setzen valid nicht auf false. Was hinter einer Regel-ID wie BR-DE-1 steckt, steht im Fehlercode-Lexikon — jede ID ist dort mit Bedeutung, Feld und Korrektur dokumentiert.
In CI/CD einbauen
Für eine Pipeline braucht es genau zwei Dinge: einen Exit-Code, der den Build stoppt, und eine Fehlerausgabe, die im Log brauchbar ist. Beides liefert jq aus der JSON-Antwort. Das folgende Skript bricht bei jeder nicht konformen Rechnung ab:
#!/usr/bin/env bash # validate.sh — bricht ab, sobald eine Rechnung nicht konform ist set -euo pipefail B64=$(base64 < "$1" | tr -d '\n') RESULT=$(curl -sS -X POST https://api.zugferd-validator.de/v1/validate \ -H "X-Api-Key: $ZUGFERD_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"file_content\":\"$B64\",\"file_type\":\"xml\"}") if [ "$(echo "$RESULT" | jq -r '.valid')" = "true" ]; then echo "OK: $1 ist konform zu EN 16931" else echo "FEHLER in $1:" echo "$RESULT" | jq -r '.errors[] | " \(.rule_id) (\(.field)): \(.message)\n Fix: \(.fix_suggestion)"' exit 1 fi
Der API-Key kommt als Secret aus der CI-Umgebung, nie ins Repository. In einer GitHub-Action ist der Aufruf danach ein Einzeiler:
# .github/workflows/e-rechnung.yml (Auszug) - name: E-Rechnung gegen EN 16931 prüfen env: ZUGFERD_API_KEY: ${{ secrets.ZUGFERD_API_KEY }} run: ./validate.sh fixtures/rechnung.xml
ZUGFeRD mit Mustang validieren: Installation, Aufruf, Report
Die Mustang-CLI ist der De-facto-Standard für lokale ZUGFeRD-Validierung — und die quelloffene Engine, die auch im Hintergrund dieser API arbeitet. Wer sie direkt nutzt, validiert vollständig offline, übernimmt aber Installation, Java-Betrieb und Aktualisierung der Regelsets selbst.
Was ist das Mustang Project?
Das Mustang Project, oft als Mustangproject geschrieben, ist die quelloffene Java-Bibliothek für ZUGFeRD und Factur-X. ZUGFeRD ist das Format, Mustang die Software, die es liest und schreibt. Zum Projekt gehört eine Kommandozeile, der Mustang-Validator, der PDF- und XML-Rechnungen gegen die Norm EN 16931 prüft und einen XML-Report mit Regel-IDs ausgibt. Dieselbe Engine arbeitet im Hintergrund unserer API, ergänzt um das KoSIT-Validierungstool.
Mustang kann mehr als prüfen: Die Bibliothek schreibt auch ZUGFeRD und fügt mit --action=combine ein PDF/A-Dokument und das XML zu einer ZUGFeRD-Rechnung zusammen. Genau so entstehen die ZUGFeRD-Rechnungen auf E-Rechnung erstellen: Wir erzeugen das PDF als PDF/A-3b, Mustang bettet das XML ein.
Installation und Aufruf
Voraussetzung ist eine Java-Laufzeitumgebung ab Version 21. Das JAR liegt im Maven-Repository beziehungsweise bei den GitHub-Releases des Mustang Projects:
# Mustang-CLI herunterladen curl -L -o Mustang-CLI-2.26.0.jar \ https://repo1.maven.org/maven2/org/mustangproject/validator/2.26.0/validator-2.26.0-shaded.jar # Java-Version prüfen (muss 21+ sein) java -version # Rechnung validieren — Ergebnis ist ein XML-Report auf stdout java -jar Mustang-CLI-2.26.0.jar --action=validate --source=rechnung.xml
Der Aufruf funktioniert für PDF und XML gleichermaßen; die Quelldatei wird über --source als Pfad übergeben. Anders als bei der API ist die Ausgabe ein XML-Report — für eine Pipeline muss der erst geparst werden, und die Regel-IDs bringen keine deutschen Korrekturvorschläge mit.
Das JAR liegt quelloffen beim Mustang Project: mustangproject.org (Projektseite) und github.com/ZUGFeRD/mustangproject (Quellcode und Releases).
Mustang-Report lesen: Regel-ID nachschlagen
Der Report ist XML und nennt nur die Regel-ID, nicht das betroffene Feld oder die Korrektur. Die IDs zieht man mit einem Griff heraus:
# Report in eine Datei schreiben und die Regel-IDs herausziehen
java -jar Mustang-CLI-2.26.0.jar --action=validate --source=rechnung.xml > report.xml
grep -o 'BR-[A-Z0-9-]*' report.xml | sort -u
Der Report nennt die Regel-ID, aber nicht, welches Feld fehlt und wie du es füllst. Das steht im Fehlercode-Lexikon: 160 Regeln mit Bedeutung, betroffenem BT-/BG-Feld, Ursache und Vorher/Nachher-XML. Häufige Treffer aus Mustang-Reports: BR-DE-1, BR-CL-10, BR-CO-11, BR-FX-EN-4.
Mustang-Validator oder Online-Validierung: was jeder Weg kann
| Mustang-Validator (lokal) | ZUGFeRD Validator (API/Online) | |
|---|---|---|
| Kosten | kostenlos, quelloffen | kostenloses Kontingent, darüber Tarif |
| Voraussetzung | Java ab 21, JAR im Container | curl, kein Java |
| Offline | ja | nein |
| Ausgabe | XML-Report | JSON |
| Fehlerbeschreibung | Regel-ID aus dem Regelsatz | Regel-ID, BT-/BG-Feld, XPath, deutscher Korrekturvorschlag |
| Regelstände aktuell halten | selbst (neues JAR einspielen) | serverseitig |
| Stapelprüfung | über eigenes Skript | Endpunkt /v1/validate/batch |
| Volumengrenze | keine | Wochenkontingent je Tarif |
Der Mustang-Validator ist quelloffen, kostenlos und der De-facto-Standard für lokale ZUGFeRD-Prüfung. Er ist außerdem die Engine, die im Hintergrund dieser API arbeitet — zusammen mit dem KoSIT-Validierungstool. Wer Java ohnehin im Stack hat und offline prüfen muss, fährt mit dem JAR richtig und braucht uns nicht. Unser Mehrwert liegt woanders: kein Java im Build, JSON statt XML-Report und ein deutscher Korrekturvorschlag pro Fehler.
XRechnung mit dem KoSIT-Validator prüfen: Aufruf, Report, Grenze
Der KoSIT-Validator, auch KoSIT-Validierungstool genannt, ist ein quelloffenes Java-Tool für XML-Rechnungen. Regeln bringt er selbst nicht mit: Was er prüft, legt eine Konfiguration fest, für XRechnung die validator-configuration-xrechnung der KoSIT. Dasselbe Tool arbeitet neben Mustang im Hintergrund unserer API.
KoSIT-Validator installieren und aufrufen
Du brauchst Java ab Version 11, das Standalone-JAR des Validators und die XRechnung-Konfiguration. Aktuell stabil sind Validator 1.6.3 und die Konfiguration vom 31.08.2026 für XRechnung 3.0.2. Mit genau diesen Ständen prüfen wir auch selbst.
# Validator (Standalone-JAR) und XRechnung-Konfiguration laden curl -L -o validator-1.6.3-standalone.jar \ https://repo1.maven.org/maven2/org/kosit/validator/1.6.3/validator-1.6.3-standalone.jar curl -L -o validator-configuration.zip \ https://github.com/itplr-kosit/validator-configuration-xrechnung/releases/download/v2026-08-31/xrechnung-3.0.2-validator-configuration-2026-08-31.zip unzip validator-configuration.zip # Rechnung prüfen: -s Szenarien, -r Ordner der Konfiguration, -h zusätzlich HTML-Bericht java -jar validator-1.6.3-standalone.jar -s scenarios.xml -r "$PWD" -h rechnung.xml
Der Dateiname wechselt mit jeder Version. Ältere Anleitungen nennen noch validationtool-*.jar, seit Version 1.5.1 heißt die Datei validator-*.jar. Alle Optionen zeigt --help.
Für viele Rechnungen lohnt der Daemon-Modus: Mit -D startet der Validator einen HTTP-Dienst, ohne weitere Angabe auf localhost und Port 8080. Du schickst jede Rechnung per POST als XML und liest das Urteil am Statuscode: 200 heißt annehmbar, 406 nicht annehmbar.
# Validator als HTTP-Dienst starten (-H Adresse, -P Port) java -jar validator-1.6.3-standalone.jar -s scenarios.xml -r "$PWD" -D -H localhost -P 8080 # Rechnung per POST prüfen, das Urteil steht im HTTP-Statuscode curl -X POST http://localhost:8080/rechnung.xml \ -H "Content-Type: application/xml" \ --data-binary @rechnung.xml
Eine Zugangskontrolle hat der Dienst nicht. Binde ihn an localhost oder setze einen Proxy wie nginx davor.
KoSIT-Report lesen: Urteil, Stufe, Regel-ID
Im CLI-Modus schreibt der Validator je Rechnung einen XML-Report in den aktuellen Ordner: Aus rechnung.xml wird rechnung-report.xml, mit -h kommt rechnung-report.html dazu. Mit -o wählst du einen anderen Ordner, mit -p landet der Report auf der Konsole. Der Report nennt das angewandte Szenario, jeden Verstoß mit Regel-ID und Stufe (error, warning oder information) und ein Gesamturteil: annehmbar oder nicht.
Für Skripte zählt der Exit-Code: 0 heißt, alle Dateien sind annehmbar. Eine positive Zahl nennt die Zahl der abgelehnten Dateien.
# Geschäftsregeln (BR-...) der gemeldeten Verstöße ziehen, Attribut code an jeder Meldung
grep -o 'code="BR-[A-Z0-9-]*"' rechnung-report.xml | sort -u
Was eine Regel-ID bedeutet, welches BT- oder BG-Feld sie meint und wie du den Fehler behebst, steht im Fehlercode-Lexikon.
Grenze des KoSIT-Validators: Er prüft XML, nicht das PDF
Der KoSIT-Validator ist laut seiner Doku eine Prüf-Engine für XML-Dateien. Bei einer ZUGFeRD-Rechnung prüfst du deshalb das eingebettete XML, das du vorher aus dem PDF holst. Die XRechnung-Konfiguration prüft UBL- und CII-Rechnungen gegen EN 16931 und XRechnung. Für die ZUGFeRD-Profile nutzen wir eine zweite, freie Konfiguration (validator-configuration-zugferd von LandrixSoftware). Unsere API nimmt das PDF direkt, holt das XML selbst heraus und antwortet mit JSON und einem deutschen Korrekturvorschlag je Fehler.
MCP-Client für KI-Agenten
Soll nicht ein Skript, sondern ein KI-Agent die Prüfung auslösen, gibt es den MCP-Client als npm-Paket. Er spricht dieselbe API, stellt sie aber als Model-Context-Protocol-Tools bereit, die Clients wie Claude, Cursor oder Windsurf selbstständig aufrufen können. Voraussetzung ist Node.js ab Version 18, Java wird nicht gebraucht.
# Global installieren … npm install -g zugferd-mcp-client # … oder ohne Installation direkt ausführen npx zugferd-mcp-client
Die Einbindung erfolgt über die MCP-Konfiguration des jeweiligen Clients. Das Binary heißt zugferd-mcp, der API-Key kommt als Umgebungsvariable:
{
"mcpServers": {
"zugferd": {
"command": "zugferd-mcp",
"env": { "ZUGFERD_API_KEY": "zv_…" }
}
}
}
Danach stehen dem Agenten vier Tools zur Verfügung: validate_invoice (prüfen), extract_xml (XML aus einer PDF holen), check_consistency (PDF-Anzeige gegen XML-Daten abgleichen) und create_invoice (valide E-Rechnung aus strukturierten Daten erzeugen).