API-Dokumentation

REST API für XRechnung und ZUGFeRD Validierung

API-Zugang

Unser Abrechnungsdienstleister für die Validator-API wartet noch auf ein bisschen Papier vom Finanzamt. Für einen Vorabzugang schreiben Sie bitte eine Email an validator@apps4everything.de

Die Validator-API ermöglicht die programmatische Validierung von XRechnungen und ZUGFeRD-Dokumenten. Die API ist kostenlos nutzbar und erfordert keine Registrierung.

Base URL

https://api.xvalidator.de

Authentifizierung

Die API kann ohne Authentifizierung genutzt werden (Rate Limit: 10 Anfragen/Stunde). Für höhere Limits kann ein API-Key verwendet werden.

Rate Limiting & Quota

Ohne API-Key 10 Validierungen pro Stunde
Mit API-Key Je nach Abo-Plan (monatliches Kontingent)

Jede Response enthält Header mit Informationen über dein aktuelles Limit:

Ohne API-Key (Rate Limiting)

Header Beschreibung
X-RateLimit-Limit Maximale Anzahl an Requests pro Stunde (10)
X-RateLimit-Remaining Verbleibende Requests in diesem Zeitfenster
X-RateLimit-Reset Unix Timestamp, wann das Limit zurückgesetzt wird

Mit API-Key (Quota)

Header Beschreibung
X-Quota-Limit Monatliches Kontingent (z.B. 1000 Validierungen)
X-Quota-Used Bereits verbrauchte Validierungen diesen Monat
X-Quota-Remaining Verbleibende Validierungen diesen Monat
# Example Response Headers without API-Key: X-RateLimit-Limit: 10 X-RateLimit-Remaining: 7 X-RateLimit-Reset: 1706097600 # Example Response Headers with API-Key: X-Quota-Limit: 1000 X-Quota-Used: 234 X-Quota-Remaining: 766

Endpoints

POST /v1/assessment

Validiert eine XRechnung oder ein ZUGFeRD-Dokument gegen den XRechnung 3.0.2 Standard.

Request

Content-Type: application/xml oder application/pdf

Body: XML-Datei (XRechnung) oder PDF-Datei (ZUGFeRD)

Headers (Optional)

Header Beschreibung
Authorization Bearer Token mit API-Key: Bearer YOUR_API_KEY

Query Parameter (Optional)

Parameter Beschreibung
output Format der Response: json für strukturiertes JSON (Standard: XML)

Response Format

Wichtig: Die API gibt standardmäßig das rohe KoSIT-Validierungs-XML zurück. Mit ?output=json erhältst du strukturiertes JSON.
Standard (ohne ?output=json)

Content-Type: application/xml

Gibt das komplette KoSIT-Validierungs-XML zurück (Prüfbericht).

<?xml version="1.0" encoding="UTF-8"?> <report xmlns="http://www.xoev.de/de/validator/varl/1"> <assessment> <accept>...</accept> </assessment> <messages>...</messages> </report>
Mit ?output=json

Content-Type: application/json

Gibt strukturiertes JSON mit geparsten Informationen zurück.

{ "valid": true, "assessment": "acceptable", "errors": 0, "warnings": 1, "messages": [ { "level": "warning", "message": "Element 'Specification identifier' (BT-24) entspricht..." } ], "reportHtml": "<div>...</div>", "rawXml": "<?xml version=\"1.0\"...>" }

JSON Response Felder

Feld Typ Beschreibung
valid boolean Ob die Rechnung formal valide ist
assessment string acceptable, reject, oder unknown
errors number Anzahl der Fehler
warnings number Anzahl der Warnungen
messages array Liste aller Fehler und Warnungen
reportHtml string HTML-Prüfbericht. Nur vorhanden wenn der KoSIT-Validator einen HTML-Report generiert.
rawXml string Das komplette KoSIT-Validierungs-XML

Beispiel: cURL (XML Response)

curl -X POST https://api.xvalidator.de/v1/assessment \ -H "Content-Type: application/xml" \ --data-binary @invoice.xml

Beispiel: cURL (JSON Response)

curl -X POST "https://api.xvalidator.de/v1/assessment?output=json" \ -H "Content-Type: application/xml" \ --data-binary @invoice.xml

Beispiel: Python

import requests with open('invoice.xml', 'rb') as f: response = requests.post( 'https://api.xvalidator.de/v1/assessment', params={'output': 'json'}, headers={'Content-Type': 'application/xml'}, data=f.read() ) # Read response headers print(f"Remaining: {response.headers.get('X-RateLimit-Remaining')}") print(f"Reset: {response.headers.get('X-RateLimit-Reset')}") # Parse response body result = response.json() print(f"Valid: {result['valid']}") print(f"Assessment: {result['assessment']}") print(f"Errors: {result['errors']}") print(f"Warnings: {result['warnings']}")

Beispiel: JavaScript

const fs = require('fs'); const axios = require('axios'); const xmlData = fs.readFileSync('invoice.xml'); axios.post('https://api.xvalidator.de/v1/assessment?output=json', xmlData, { headers: { 'Content-Type': 'application/xml' } }) .then(response => { // Response Headers console.log('Remaining:', response.headers['x-ratelimit-remaining']); console.log('Reset:', response.headers['x-ratelimit-reset']); // Response Body console.log('Valid:', response.data.valid); console.log('Assessment:', response.data.assessment); console.log('Errors:', response.data.errors); console.log('Warnings:', response.data.warnings); }) .catch(error => console.error(error));

Beispiel: PHP

$xml = file_get_contents('invoice.xml'); $ch = curl_init('https://api.xvalidator.de/v1/assessment?output=json'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/xml' ]); $response = curl_exec($ch); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $headerSize); $body = substr($response, $headerSize); curl_close($ch); // Parse response headers preg_match('/X-RateLimit-Remaining: (\d+)/', $headers, $remaining); echo "Remaining: " . ($remaining[1] ?? 'N/A') . "\n"; // Parse response body $result = json_decode($body, true); echo "Valid: " . ($result['valid'] ? 'Yes' : 'No') . "\n"; echo "Assessment: " . $result['assessment'] . "\n"; echo "Errors: " . $result['errors'] . "\n"; echo "Warnings: " . $result['warnings'] . "\n";

POST /v1/preview

Generiert eine HTML-Vorschau einer XRechnung oder eines ZUGFeRD-Dokuments.

Request

Content-Type: application/xml oder application/pdf

Body: XML-Datei (XRechnung) oder PDF-Datei (ZUGFeRD)

Response

Content-Type: text/html

Gibt direkt HTML zurück, das die Rechnung in lesbarer Form darstellt.

Beispiel: cURL

curl -X POST https://api.xvalidator.de/v1/preview \ -H "Content-Type: application/xml" \ --data-binary @invoice.xml \ -o preview.html

Beispiel: Python

import requests with open('invoice.xml', 'rb') as f: response = requests.post( 'https://api.xvalidator.de/v1/preview', headers={'Content-Type': 'application/xml'}, data=f.read() ) with open('preview.html', 'w', encoding='utf-8') as f: f.write(response.text)

Fehler-Responses

400 Bad Request

{ "error": "No content provided" }

Der Request-Body ist leer oder ungültig.

401 Unauthorized

{ "error": "Invalid API key", "message": "Invalid api key" }

Der API-Key ist ungültig oder fehlt.

402 Payment Required

{ "error": "Quota exhausted", "message": "Monthly limit of 1000 validations reached.", "usage": 1000, "limit": 1000, "resets": "2026-02-01" }

Das monatliche Kontingent ist aufgebraucht.

403 Forbidden

{ "error": "Subscription not valid" }

Die Subscription ist nicht aktiv.

413 Payload Too Large

{ "error": "File too large. Maximum size: 5MB" }

Die Datei überschreitet die maximale Größe von 5MB.

429 Too Many Requests

{ "error": "Rate limit exceeded", "message": "Limit of 10 requests per hour exceeded. Please try again later.", "limit": 10, "reset": "2026-01-24 15:30:00" }

Das Rate Limit wurde überschritten. Das Feld reset zeigt den Zeitpunkt der Zurücksetzung.

503 Service Unavailable

{ "error": "Service temporarily unavailable", "message": "Please try again in a few minutes." }

Der Validator-Service ist temporär nicht verfügbar.

Limits

Limit Wert
Maximale Dateigröße 5 MB
Rate Limit (ohne API-Key) 10 Anfragen pro Stunde
Request Timeout 30 Sekunden
Unterstützte Formate XML (XRechnung), PDF (ZUGFeRD)

Best Practices

Response Headers überwachen

Lies die X-RateLimit-* oder X-Quota-* Header, um dein Limit zu überwachen und Anfragen entsprechend zu throtteln.

Response Format wählen

Nutze ?output=json wenn du strukturierte Daten verarbeiten möchtest. Das XML-Format ist nützlich, wenn du den kompletten KoSIT-Prüfbericht speichern willst.

Fehlerbehandlung

Implementiere immer Retry-Logik für 503-Fehler. Bei 429-Fehlern beachte das reset-Feld, das den Zeitpunkt der Zurücksetzung angibt.

Dateigröße

Prüfe die Dateigröße client-seitig, um unnötige Uploads zu vermeiden (max. 5MB).

Timeouts

Setze Request-Timeouts auf mindestens 35 Sekunden, um dem Server Zeit für die Validierung zu geben.

Caching

Cache Validierungsergebnisse für identische Dateien, um API-Calls zu sparen.