Core API

Validator API

Validiere E-Rechnungen gegen offizielle KoSIT-Schemas und Schematron-Regeln. Erhalte detaillierte Fehlermeldungen mit Korrekturvorschlägen.

POST/api/v1/invoice/{countryCode}/validate
API-Key erforderlich

Validierung läuft nur mit gültigem Bearer-Key. Ohne Key antwortet der Endpoint mit 401.

Vor dem Versand prüfen

Finde Formatfehler, bevor die Rechnung beim Empfänger liegt — mit Fehlermeldung und Korrekturhinweis.

KoSIT-konform

Offizielle Schematron-Regeln der KoSIT (Koordinierungsstelle für IT-Standards)

37 Länder

Unterstützung für AE, AT, AU, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GR, HR, HU, IE, IS, IT, JP, LI, LT, LU, LV, MT, NL, NO, NZ, OM, PL, PT, RO, SE, SI, SK

Alle Formate

XRechnung, ZUGFeRD, Factur-X, Peppol UBL sowie nationale Formate (FatturaPA, ebInterface, Facturae, ISDOC, NAV, myDATA, KSeF FA(3), eFactura/CIUS-RO, CIUS-PT, QR-Bill) werden unterstützt — die vollständige Tabelle steht weiter unten.

Beispiel

bash
1curl -X POST 'https://service.invoice-api.xhub.io/api/v1/invoice/de/validate' \
2 -H 'Authorization: Bearer sk_test_xxx' \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "invoice": {
6 "invoiceNumber": "RE-2026-001",
7 "type": "invoice",
8 "issueDate": "2026-01-15",
9 "dueDate": "2026-02-15",
10 "currency": "EUR",
11 "seller": {
12 "name": "Meine Firma GmbH",
13 "street": "Musterstraße 1",
14 "city": "Berlin",
15 "postalCode": "10115",
16 "countryCode": "DE",
17 "vatId": "DE123456789"
18 },
19 "buyer": {
20 "name": "Kunde AG",
21 "street": "Kundenweg 42",
22 "city": "München",
23 "postalCode": "80331",
24 "countryCode": "DE",
25 "vatId": "DE987654321"
26 },
27 "items": [{
28 "position": 1,
29 "description": "Beratung",
30 "quantity": 10,
31 "unit": "HUR",
32 "unitPrice": 150.00,
33 "taxRate": 19,
34 "netAmount": 1500.00,
35 "taxAmount": 285.00,
36 "grossAmount": 1785.00
37 }],
38 "subtotal": 1500.00,
39 "total": 1785.00,
40 "taxSummary": [{ "taxRate": 19, "netAmount": 1500.00, "taxAmount": 285.00 }],
41 "paymentTerms": { "dueDays": 30 }
42 }
43 }'

Ein Format gezielt prüfen

POST/api/v1/invoice/{countryCode}/{format}/validate

Neben der Länder-Route gibt es eine Route je Format. Sie erzeugt die Rechnung genau in diesem Format und schickt das Ergebnis durch dessen XSD und Schematron — statt durch die aller Formate des Landes.

Länder-Route

/api/v1/invoice/{countryCode}/validate

Prüft alle Formate des Landes und zusätzlich die fachlichen Landesregeln. Für DE ergibt die Rechnung oben elf Einträge in results[] — XRechnung und zehn ZUGFeRD-Profile — und in errors[] die Codes DE_REF_002 und DE_SELLER_CONTACT_001 (gemessen am 2026-09-15).

Format-Route

/api/v1/invoice/{countryCode}/{format}/validate

Prüft genau ein Format. Bei ZUGFeRD und Factur-X wird jedes Profil erzeugt und geprüft, deshalb stehen dort mehrere Einträge in results[]. Die fachlichen Landesregeln laufen hier nicht mit: valid bezieht sich allein auf das erzeugte XML.

Pfadparameter format

Die Spec kennt diese Werte, immer klein geschrieben:

ebinterfaceebInterfacefacturaeFacturaefacturxFactur-XfatturapaFatturaPAhr-fiskHR-FISKisdocISDOCksefKSeFmydatamyDATAnavNAVpdfPDFpeppol-ublPeppol UBLqr-billQR-BillublUBLxrechnungXRechnungzugferdZUGFeRD

Welche davon ein Land wirklich als prüfbares XML-Format führt, hängt vom Land ab — die Liste je Land liefert der formats-Endpoint. Ein Wert, den das Land nicht führt, wird mit 400 abgewiesen: /de/pdf/validate antwortet mit „Format 'pdf' is not a validatable XML format for country DE“ (gemessen am 2026-09-15).

Request

bash
1curl -X POST 'https://service.invoice-api.xhub.io/api/v1/invoice/de/zugferd/validate' \
2 -H 'Authorization: Bearer sk_test_xxx' \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "invoice": {
6 "invoiceNumber": "RE-2026-001",
7 "type": "invoice",
8 "issueDate": "2026-01-15",
9 "dueDate": "2026-02-15",
10 "currency": "EUR",
11 "seller": {
12 "name": "Meine Firma GmbH",
13 "street": "Musterstraße 1",
14 "city": "Berlin",
15 "postalCode": "10115",
16 "countryCode": "DE",
17 "vatId": "DE123456789"
18 },
19 "buyer": {
20 "name": "Kunde AG",
21 "street": "Kundenweg 42",
22 "city": "München",
23 "postalCode": "80331",
24 "countryCode": "DE",
25 "vatId": "DE987654321"
26 },
27 "items": [{
28 "position": 1,
29 "description": "Beratung",
30 "quantity": 10,
31 "unit": "HUR",
32 "unitPrice": 150.00,
33 "taxRate": 19,
34 "netAmount": 1500.00,
35 "taxAmount": 285.00,
36 "grossAmount": 1785.00
37 }],
38 "subtotal": 1500.00,
39 "total": 1785.00,
40 "taxSummary": [{ "taxRate": 19, "netAmount": 1500.00, "taxAmount": 285.00 }],
41 "paymentTerms": { "dueDays": 30 }
42 }
43 }'

Antwort

Dieselbe Rechnung wie oben, an /de/zugferd/validate geschickt — die Antwort des Dienstes vom 2026-09-15, unverändert:

json
1{
2 "valid": true,
3 "results": [
4 { "format": "zugferd-2.4-minimum", "valid": true, "errors": [] },
5 { "format": "zugferd-2.4-en16931", "valid": true, "errors": [] },
6 { "format": "zugferd-2.4-basic", "valid": true, "errors": [] },
7 { "format": "zugferd-2.4-basic-wl", "valid": true, "errors": [] },
8 { "format": "zugferd-2.4-extended", "valid": true, "errors": [] },
9 { "format": "zugferd-2.5-minimum", "valid": true, "errors": [] },
10 { "format": "zugferd-2.5-en16931", "valid": true, "errors": [] },
11 { "format": "zugferd-2.5-basic", "valid": true, "errors": [] },
12 { "format": "zugferd-2.5-basic-wl", "valid": true, "errors": [] },
13 { "format": "zugferd-2.5-extended", "valid": true, "errors": [] }
14 ]
15}

An /de/xrechnung/validate ergibt dieselbe Rechnung valid: false, einen Eintrag in results[] (xrechnung-3.0.2-ubl) und die Regelcodes PEPPOL-EN16931-R020, BR-DE-1, BR-DE-6, BR-DE-7 und BR-DE-15. Jeder Eintrag trägt dort location (XPath) und severity; dieselben Funde stehen zusätzlich flach in errors[].

Auth und Kontingent wie bei der Länder-Route: ein Bearer-Key ist Pflicht (ohne ihn 401), und der Aufruf ist an das Monatskontingent des Schlüssels gebunden — ist es erschöpft, antwortet auch diese Route mit 429. Plane sie wie einen Erzeugungsaufruf ein: die Prüfung erzeugt den Beleg intern.

Unterstützte Länder

Der Ländercode wird als Teil der URL angegeben: /api/v1/invoice/{countryCode}/validate

DE

Deutschland

AT

Österreich

CH

Schweiz

FR

Frankreich

IT

Italien

ES

Spanien

NL

Niederlande

BE

Belgien

PL

Polen

PT

Portugal

AE

Vereinigte Arabische Emirate

AU

Australien

BG

Bulgarien

CY

Zypern

CZ

Tschechien

DK

Dänemark

EE

Estland

FI

Finnland

GB

Großbritannien

GR

Griechenland

HR

Kroatien

HU

Ungarn

IE

Irland

IS

Island

JP

Japan

LI

Liechtenstein

LT

Litauen

LU

Luxemburg

LV

Lettland

MT

Malta

NO

Norwegen

NZ

Neuseeland

OM

Oman

RO

Rumänien

SE

Schweden

SI

Slowenien

SK

Slowakei

= Verfügbar

Deutschland

/api/v1/invoice/de/validate

Österreich

/api/v1/invoice/at/validate

Frankreich

/api/v1/invoice/fr/validate

Italien

/api/v1/invoice/it/validate

Schweiz

/api/v1/invoice/ch/validate

Spanien

/api/v1/invoice/es/validate

Request Parameter

Path Parameter

ParameterTypPflichtBeschreibung
countryCodestringISO 3166-1 alpha-2 Ländercode. Verfügbar (37): AE, AT, AU, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GR, HR, HU, IE, IS, IT, JP, LI, LT, LU, LV, MT, NL, NO, NZ, OM, PL, PT, RO, SE, SI, SK.

Headers & Body

ParameterTypPflichtBeschreibung
AuthorizationheaderBearer Token mit sk_test_* oder sk_live_* API Key
Content-Typeheaderapplication/json
invoiceobject (body)Das zu validierende invoice-Objekt (JSON). Der Endpoint nimmt ausschließlich einen JSON-Body mit dem Feld invoice entgegen — kein Roh-XML, kein Datei-Upload.

Authentifizierung

Verwende deinen API Key im Authorization-Header: für Testumgebung oder für Produktion.Bearer sk_test_... / Bearer sk_live_...

Response

Gültige Rechnung

200 OK
json
1{
2 "valid": true,
3 "errors": [],
4 "warnings": []
5}

Ungültige Rechnung

200 OK
json
1{
2 "valid": false,
3 "errors": [
4 {
5 "code": "BR-DE-1",
6 "message": "Eine Rechnung (INVOICE) muss Angaben zu "PAYMENT INSTRUCTIONS" (BG-16) enthalten.",
7 "field": "/Invoice/cac:PaymentMeans"
8 },
9 {
10 "code": "BR-DE-15",
11 "message": "Das Element "Buyer reference" (BT-10) muss übermittelt werden.",
12 "field": "/Invoice/cbc:BuyerReference"
13 }
14 ],
15 "warnings": [
16 {
17 "code": "MISSING_OPTIONAL",
18 "message": "Delivery date is recommended",
19 "field": "deliveryDate"
20 }
21 ]
22}

Error Responses

400 Bad Request
json
1{
2 "error": "Bad Request",
3 "message": "Invoice data is required"
4}
401 Unauthorized
json
1{
2 "error": "UNAUTHORIZED",
3 "message": "Invalid or missing API key"
4}
500 Internal Server Error
json
1{
2 "error": "INTERNAL_ERROR",
3 "message": "An unexpected error occurred"
4}

Response-Felder

valid

true / false

errors

Array von Fehlern. Jeder Fehler enthält code, message und optional field.

warnings

Array von Warnungen. Gleiches Schema wie Fehler, aber keine kritischen Probleme.

Schema für Errors/Warnings

FeldTypBeschreibung
codestringFehlercode (z.B. BR-DE-01, BR-16)
messagestringLesbare Fehlerbeschreibung
fieldstring (optional)XPath oder Feldname, wo der Fehler aufgetreten ist

Unterstützte Formate

FormatSchemaValidierung
XRechnung 3.0.2EN16931 CII/UBLKoSIT 3.0.2 Schematron
XRechnung 3.0EN16931 CII/UBLKoSIT 3.0 Schematron
ZUGFeRD 2.5EN16931 CIIEN16931 Schematron
ZUGFeRD 2.4EN16931 CIIEN16931 Schematron
ZUGFeRD 2.3EN16931 CIIEN16931 Schematron
Factur-X 1.09EN16931 CIIEN16931 Schematron
Factur-X 1.08EN16931 CIIEN16931 Schematron
Factur-X 1.0EN16931 CIIEN16931 Schematron
UBL (Peppol BIS 3.0)EN16931 UBLPeppol BIS 3.0 / EN16931
ebInterfaceebInterface XSD (AT)ebInterface
FatturaPA 1.2.3FatturaPA XSD (IT)SDI-Schema
FacturaeFacturae XSD (ES)Facturae XSD
ISDOCISDOC XSD (CZ)ISDOC XSD
NAVNAV XSD (HU)NAV-Online XSD
myDATAmyDATA XSD (GR)myDATA XSD
KSeF FA(3)KSeF UBL-Slot (PL)KSeF FA(3) XSD
eFactura (CIUS-RO)EN16931 UBLCIUS-RO
CIUS-PTEN16931 UBLCIUS-PT
QR-BillSwiss QR-Bill (CH/LI)QR-Bill Spezifikation

Häufige Validierungsfehler

BR-DE-1

Zahlungsangaben fehlen: Eine Rechnung muss Angaben zur Zahlung (BG-16) enthalten

Lösung: Setze paymentMethods (z. B. bank_transfer) und dazu seller.bankAccount mit IBAN

BR-DE-15

Käuferreferenz fehlt: Das Element Buyer reference (BT-10) muss übermittelt werden

Lösung: Setze countrySpecific.buyerReference — bei öffentlichen Auftraggebern die Leitweg-ID in countrySpecific.leitwegId

BR-DE-17

Unzulässiger Rechnungstyp: Der Rechnungstyp-Code (BT-3) muss 326, 380, 384, 389, 381, 875, 876 oder 877 sein

Lösung: Setze invoice.type auf einen zulässigen Wert (invoice = 380); proforma ist in XRechnung nicht erlaubt

BR-16

Keine Rechnungsposition: Eine Rechnung muss mindestens eine Position (BG-25) enthalten

Lösung: Füge mindestens einen Eintrag in items hinzu

BR-CO-10

Summe der Positionsnettobeträge ungleich Rechnungsnetto

Lösung: Prüfe die Summe aller items[].quantity * items[].unitPrice

Vollständige Fehlerliste: Error Handling Dokumentation

Für die Zahl der Rechnungspositionen gilt auf beiden Prüf-Routen dieselbe tarifabhängige Grenze wie beim Erzeugen — darüber antwortet die API mit HTTP 400 und TOO_MANY_LINE_ITEMS: Grenzen in der Creator-API

Validierung und dein Kontingent

Der Validierungsaufruf wird deinem monatlichen Kontingent nicht angerechnet — er ist aber daran gebunden: Ist das Kontingent aufgebraucht, antwortet auch die Validierung mit 429. Plane das ein, wenn du in CI/CD-Pipelines oder automatischen Tests validierst.

Validierung im Playground

Im Playground kannst du die Validierung ohne eigenen API-Key ausprobieren — die Anfrage läuft dort über unseren Schlüssel und ist pro IP begrenzt. Der Endpoint selbst verlangt immer einen Bearer-Key.

Zum Playground →