E-Rechnungs·Validator
REST API v1
Programmatische Validierung von XRechnung, ZUGFeRD und Factur-X. Alle Endpunkte liegen unter /api/v1/ relativ zur Basis-URL der Installation. v1 ist deprecated — neue Integrationen nutzen /api/v2/ (gleiche Endpunkte und Payloads, gehärtete Auth mit Scopes).
Alle Endpunkte erfordern einen API-Key im Request-Header:
X-API-Key: erv_<ihr-key>
API-Keys werden im Admin-Panel unter Admin → API-Keys erstellt und verwaltet. Der Klartext-Key wird nur einmalig bei der Erstellung angezeigt. Ein fehlender, ungültiger oder widerrufener Key führt zu 401 INVALID_API_KEY.
Key-Scoping: Validierungsergebnisse sind nur mit demselben API-Key abrufbar, mit dem sie eingereicht wurden. Fremde oder unbekannte Validation-Keys liefern 404.
/api/v2/ bietet exakt dieselben sieben Endpunkte mit identischen Payloads wie v1 — es ändert sich nur die Basis-URL. Die Authentifizierung läuft weiterhin über den X-API-Key-Header, ist aber gehärtet: Jeder Key erhält Scopes sowie optional ein Ablaufdatum, eine IP-Allowlist und ein eigenes Rate-Limit. v1 ist deprecated (alle v1-Responses tragen den Header Deprecation: true), läuft aber unverändert weiter.
Scopes sind pro Key frei kombinierbar und werden im Admin-Panel unter Admin → API-Keys vergeben (beim Erstellen und beim Bearbeiten). Ein v2-Aufruf ohne den passenden Scope liefert 403 SCOPE_MISSING.
| Scope | Erlaubte Endpunkte |
|---|---|
validate | POST /validate (sync & async), POST /visualize, POST /validate-and-visualize, POST /batch |
results:read | GET /results/{validation_key}, GET /results |
results:ack | POST /results/ack |
| HTTP | Code | Bedeutung |
|---|---|---|
| 401 | KEY_EXPIRED | Ablaufdatum überschritten — der Key gilt bis einschließlich des Ablaufdatums (greift auch in v1) |
| 403 | IP_NOT_ALLOWED | Aufrufer-IP steht nicht in der IP-Allowlist des Keys |
| 403 | SCOPE_MISSING | Key besitzt den für diesen Endpunkt nötigen Scope nicht |
| 429 | RATE_LIMITED | Rate-Limit überschritten — der Retry-After-Header nennt die Wartezeit in Sekunden |
Das Rate-Limit beträgt standardmäßig 120 Requests pro Minute und ist pro Key übersteuerbar. Zusätzlich greift eine Brute-Force-Bremse: maximal 10 fehlgeschlagene Auth-Versuche pro Minute und IP. Ablaufdatum, IP-Allowlist und individuelles Rate-Limit werden je Key im Admin-Panel konfiguriert.
/api/v1/ → /api/v2/ in der Integration.Key-Rotation: Neuen Key mit denselben Scopes anlegen und dem alten Key ein Ablaufdatum setzen — so läuft der alte Key kontrolliert aus, ohne die Integration zu unterbrechen.
Alle Fehler haben dieses Format:
{ "error": "Beschreibung", "code": "ERROR_CODE" }
| HTTP | Code | Bedeutung |
|---|---|---|
| 401 | INVALID_API_KEY | Key fehlt, ungültig oder widerrufen |
| 400 | MISSING_FILE | Kein file-Feld im Request |
| 400 | INVALID_MODE | mode nicht in mustang, kosit, both |
| 400 | TOO_MANY_FILES | Mehr als 50 Dateien im Batch-Request |
| 413 | FILE_TOO_LARGE | Datei > 10 MB |
| 400 | MISSING_FILTER | Sammelabruf ohne unfetched und ohne from/to |
| 400 | INVALID_DATE | from/to ist kein gültiges ISO-Datum |
| 400 | INVALID_PAGINATION | limit/offset nicht numerisch |
| 400 | MISSING_KEYS | Ack ohne keys-Liste |
| 400 | TOO_MANY_KEYS | Mehr als 200 Keys pro Ack-Request |
| 404 | UNKNOWN_KEY | Validation-Key unbekannt oder gehört zu einem anderen API-Key |
| 500 | VALIDATOR_ERROR | Java-Fehler oder Validator-JAR nicht gefunden |
| 500 | VISUALIZATION_ERROR | Visualisierung fehlgeschlagen |
status im Ergebnis: valid | warn | invalid | error
Beim Abruf per Validation-Key kann das status-Feld zusätzlich den Lebenszyklus abbilden: pending (in Verarbeitung, HTTP 202) und error mit Feld error (Job fehlgeschlagen, z. B. nach Server-Neustart).
Validiert eine einzelne E-Rechnungs-Datei (XML oder ZUGFeRD-/Factur-X-PDF).
| Feld | Typ | Pflicht | Default | Beschreibung |
|---|---|---|---|---|
file | Datei | Ja | — | Rechnung (multipart/form-data) |
mode | String | Nein | mustang | mustang | kosit | both |
async | String | Nein | — | true: sofortige Annahme, Validierung im Hintergrund NEU |
curl -X POST https://einvoice-validator.de/api/v1/validate \
-H "X-API-Key: erv_abc123..." \
-F "file=@rechnung.xml" \
-F "mode=both"
Response 200:
{
"validation_id": 42,
"validation_key": "3f9c2a7b1e8d4c6a9b0f2e5d8c1a4b7e",
"filename": "rechnung.xml",
"mode": "both",
"status": "valid",
"format": "XRechnung",
"profile": "urn:cen.eu:en16931:2017",
"issues": [],
"mustang_result": { "status": "valid", "issues": [] },
"kosit_result": { "status": "valid", "issues": [] }
}
validation_key ist der eindeutige Schlüssel dieser Validierung — damit lässt sich das Ergebnis jederzeit erneut abrufen (siehe Einzelabruf).
curl -X POST https://einvoice-validator.de/api/v1/validate \
-H "X-API-Key: erv_abc123..." \
-F "file=@rechnung.xml" \
-F "async=true"
Response 202:
{
"validation_key": "3f9c2a7b1e8d4c6a9b0f2e5d8c1a4b7e",
"status": "pending",
"filename": "rechnung.xml",
"mode": "mustang"
}
Die Datei wird sofort angenommen, die Validierung läuft im Hintergrund. Das Ergebnis holen Sie später per Key ab. Ungültige Requests (Datei fehlt, falscher Modus, Datei zu groß) werden auch im Async-Fall sofort synchron abgelehnt.
Erzeugt eine HTML-Visualisierung der Rechnung, ohne zu validieren.
| Feld | Typ | Pflicht | Default |
|---|---|---|---|
file | Datei | Ja | — |
style | String | Nein | compact (compact | full) |
Response 200: { "filename": "...", "style": "compact", "visualization_html": "<Base64>" }
visualization_html ist Base64-kodiertes HTML. Dekodierung: Python base64.b64decode(...), JavaScript atob(...), Shell base64 -d.
Kombiniert beide Aufrufe. Parameter: file (Pflicht), mode, style. Response wie /validate (inkl. validation_key) plus visualization_html; schlägt nur die Visualisierung fehl, ist stattdessen visualization_error gesetzt.
Validiert bis zu 50 Dateien in einem Request (synchron).
| Feld | Typ | Pflicht | Default |
|---|---|---|---|
files[] | Dateien | Ja | — |
mode | String | Nein | mustang |
curl -X POST https://einvoice-validator.de/api/v1/batch \
-H "X-API-Key: erv_abc123..." \
-F "files[]=@rechnung1.xml" \
-F "files[]=@rechnung2.xml"
Response 200:
{
"summary": { "total": 2, "valid": 1, "warn": 0, "invalid": 1 },
"results": [
{ "validation_id": 43, "validation_key": "a1b2...", "filename": "rechnung1.xml",
"status": "valid", "issues": [] },
{ "validation_id": 44, "validation_key": "c3d4...", "filename": "rechnung2.xml",
"status": "invalid", "issues": [{ "type": "error", "msg": "...", "rule": "BR-01" }] }
]
}
Ruft das gespeicherte Ergebnis einer Validierung erneut ab. Der Abruf verändert den Abhol-Status nicht.
| HTTP | Bedeutung |
|---|---|
| 200 | Ergebnis fertig (status = Validierungsstatus) oder Job fehlgeschlagen (status: "error" + Feld error) |
| 202 | Job läuft noch (status: "pending") — später erneut abrufen |
| 404 | Key unbekannt oder gehört zu einem anderen API-Key |
curl https://einvoice-validator.de/api/v1/results/3f9c2a7b1e8d4c6a9b0f2e5d8c1a4b7e \
-H "X-API-Key: erv_abc123..."
Response 200 (fertig):
{
"validation_key": "3f9c2a7b1e8d4c6a9b0f2e5d8c1a4b7e",
"validation_id": 42,
"filename": "rechnung.xml",
"mode": "mustang",
"created_at": "2026-07-30T09:15:22",
"status": "valid",
"format": "XRechnung",
"profile": "urn:cen.eu:en16931:2017",
"issues": [],
"report_xml": "...",
"returncode": 0,
"abgeholt_am": null,
"mustang_result": { "status": "valid", "issues": [] },
"kosit_result": null
}
abgeholt_am ist der Zeitstempel der Bestätigung (siehe Ack) — null, solange das Ergebnis nicht bestätigt wurde.
Ruft mehrere Ergebnisse des eigenen API-Keys ab. Mindestens ein Filter ist Pflicht.
| Parameter | Beschreibung |
|---|---|
unfetched=true | Nur fertige (done/error), noch nicht bestätigte Ergebnisse |
from / to | ISO-Datum (2026-07-30) oder Datum+Zeit; auch einzeln nutzbar. to ohne Zeitanteil zählt bis Tagesende |
limit / offset | Pagination — Default 50, Maximum 200 |
unfetched und from/to sind kombinierbar. Beim reinen Zeitraum-Abruf erscheinen auch laufende Jobs (als status: "pending"-Objekt); bei unfetched=true nicht.
# Alle noch nicht abgeholten Ergebnisse
curl "https://einvoice-validator.de/api/v1/results?unfetched=true" \
-H "X-API-Key: erv_abc123..."
# Alle Ergebnisse eines Zeitraums
curl "https://einvoice-validator.de/api/v1/results?from=2026-07-01&to=2026-07-31" \
-H "X-API-Key: erv_abc123..."
Response 200:
{
"results": [ { ...volles Ergebnis wie beim Einzelabruf... } ],
"count": 1,
"limit": 50,
"offset": 0
}
Markiert Ergebnisse als abgeholt. Bestätigte Ergebnisse erscheinen nicht mehr im unfetched-Abruf, bleiben aber per Key und Zeitraum abrufbar. Der Aufruf ist idempotent — bereits bestätigte Keys zählen erneut als acked.
curl -X POST https://einvoice-validator.de/api/v1/results/ack \
-H "X-API-Key: erv_abc123..." \
-H "Content-Type: application/json" \
-d '{ "keys": ["3f9c2a7b1e8d4c6a9b0f2e5d8c1a4b7e"] }'
Response 200: { "acked": 1, "unknown": [] }
unknown enthält Keys, die unbekannt sind, einem anderen API-Key gehören oder deren Job noch läuft. Maximal 200 Keys pro Request.
Empfohlener Ablauf für die Hintergrund-Validierung:
POST /api/v1/validate mit async=true → 202 mit validation_key speichern.GET /api/v1/results/{key} pollen, bis statt 202 ein 200 kommt.GET /api/v1/results?unfetched=true aufrufen — liefert alle fertigen, noch nicht bestätigten Ergebnisse (auch fehlgeschlagene Jobs).POST /api/v1/results/ack quittieren, damit sie beim nächsten unfetched-Abruf nicht erneut erscheinen.Server-Neustart: Wird der Server während der Verarbeitung neu gestartet, erhalten offene Jobs status: "error" mit dem Hinweis „Server-Neustart während der Verarbeitung" — die Rechnung dann einfach neu einreichen.
| Limit | Wert |
|---|---|
| Maximale Dateigröße | 10 MB pro Datei |
| Batch-Größe | 50 Dateien pro Request |
| Sammelabruf | limit maximal 200 pro Seite |
| Ack | 200 Keys pro Request |