API · E-Rechnung
xmoo E-Invoice API
Europäische E-Rechnungen prüfen, auslesen, umwandeln und darstellen – XRechnung, ZUGFeRD, Factur-X und jede Rechnung nach EN 16931 in UBL oder CII – mit einem REST-Aufruf.
Was sie kann
- Prüfen mit den offiziellen Artefakten: XML-Schema, die EN-16931-Prüfregeln des CEN, das XRechnung-Schematron der KoSIT und die ZUGFeRD-/Factur-X-Regeln je Profil. Du bekommst jede Meldung mit Regel-ID, Schwere und Fundstelle und dazu die nachgerechneten Summen.
- Auslesen einer XML oder eines hybriden PDFs in ein JSON-Modell nach den Geschäftsbegriffen (BT/BG) der EN 16931 – dasselbe Modell für UBL und CII.
- Umwandeln zwischen XRechnung (UBL oder CII) und ZUGFeRD / Factur-X (XML oder PDF/A-3). Die API erfindet nichts: Braucht das Zielformat Angaben, die in der Rechnung fehlen, sagt sie genau, was du schicken musst. Ein Ergebnis kommt nur zurück, wenn es die offizielle Prüfung besteht.
- Darstellen als lesbares A4-PDF, etwa fürs Archiv oder für alle, die keine XML öffnen können.
Rechnungen werden nur im Arbeitsspeicher verarbeitet und nie gespeichert. Die API läuft auf einem Server in Helsinki, Finnland (EU), mit demselben Kern wie die kostenlosen Browser-Tools hier, der E-Rechnung-Viewer und der E-Rechnung-Konverter.
Die Dokumentation ist auf Englisch maßgeblich: E-Invoice
API (English). Feldnamen und Standardtexte der API sind englisch, mit lang=de kommen
die Texte auf Deutsch.
Zugang
Die API wird über RapidAPI angeboten. Dort wählst du einen Tarif, bekommst deinen Schlüssel und den Hostnamen für deine Anfragen; abgerechnet wird ebenfalls über RapidAPI: xmoo E-Invoice API bei RapidAPI. Fragen: julian@haag-automation.com.
Jede Anfrage trägt zwei Köpfe aus deinem RapidAPI-Konto:
x-rapidapi-key: <dein Schlüssel> x-rapidapi-host: <Hostname aus dem Eintrag>
Die Beispiele unten erwarten beides in den Shell-Variablen RAPIDAPI_KEY und
RAPIDAPI_HOST.
Endpunkte
| Endpunkt | Zweck | Antwort |
|---|---|---|
| POST /v1/detect | Format, Syntax, Spezifikation und Profil; welche Regelwerke gelten | JSON |
| POST /v1/validate | Prüfbericht mit allen Meldungen und Summenkontrolle (BR-CO-10 bis 16) | JSON |
| POST /v1/parse | Alle Geschäftsbegriffe der EN 16931 als JSON | JSON |
| POST /v1/convert?to=… | Umwandeln in xrechnung-ubl, xrechnung-cii, zugferd (XML) oder zugferd-pdf (PDF/A-3) | JSON mit der Datei als Base64 |
| POST /v1/render | Lesbares A4-PDF der Rechnung | |
| GET /v1/formats | Unterstützte Formate, Regelwerke und Ziele | JSON |
Die maschinenlesbare Beschreibung liegt unter api.xmoo.app/openapi.json (OpenAPI 3.0).
Rechnung schicken
Schick einen JSON-Body mit der Datei (XML oder PDF) als Base64 in document. Das ist der
empfohlene Weg und geht bei jedem Endpunkt:
base64 -w0 rechnung.xml | jq -Rs '{document: .}' |
curl -s -X POST "https://$RAPIDAPI_HOST/v1/validate" \
-H "x-rapidapi-key: $RAPIDAPI_KEY" \
-H "x-rapidapi-host: $RAPIDAPI_HOST" \
-H "Content-Type: application/json" \
--data-binary @-
Dasselbe in Python:
import base64, os, requests
with open("rechnung.pdf", "rb") as f:
body = {"document": base64.b64encode(f.read()).decode()}
r = requests.post(f"https://{os.environ['RAPIDAPI_HOST']}/v1/validate", json=body, headers={
"x-rapidapi-key": os.environ["RAPIDAPI_KEY"],
"x-rapidapi-host": os.environ["RAPIDAPI_HOST"],
})
bericht = r.json()
print(bericht["valid"], bericht["summary"])
Die API nimmt die Datei auch roh als Body an (Content-Type: application/xml oder
application/pdf); Optionen stehen dann in der Adresse. Weitere Felder des JSON-Bodys:
to (Zielformat bei /v1/convert), additions (siehe unten) und
lang.
Sprache
Feldnamen sind immer englisch. Beschreibende Texte – Änderungen, Verluste, Hinweise und
Fehlermeldungen – sind standardmäßig englisch, mit lang=de deutsch. Regeltexte kommen
wörtlich aus den offiziellen Artefakten: die der EN 16931 und von ZUGFeRD / Factur-X auf
Englisch, die der XRechnung-Regeln der KoSIT (BR-DE-…) auf Deutsch.
Beispiele
Die Antworten unten sind echte Antworten der API (wo vermerkt gekürzt). Testdateien: die XRechnung-Testsuite der KoSIT und die ZUGFeRD-Beispiele des Mustang-Projekts. Ein Test bei uns schickt genau diese Anfragen und prüft, dass die Antworten noch stimmen.
Hybrides PDF erkennen
POST /v1/detect mit einem ZUGFeRD-PDF im Profil EN 16931:
{
"source": "pdf",
"syntax": "CII",
"documentType": "invoice",
"specification": "urn:cen.eu:en16931:2017",
"profile": "EN 16931 (for ZUGFeRD: profile EN 16931)",
"rulesets": [
"schema-facturx-en16931",
"facturx-en16931"
]
}
XRechnung prüfen
POST /v1/validate mit einer XRechnung 3.0 in UBL. Die Rechnung ist gültig; die
KoSIT-Regeln geben einen Hinweis (Schwere info). Gekürzt auf die ersten beiden
Summenprüfungen:
{
"source": "xml",
"syntax": "UBL",
"documentType": "invoice",
"specification": "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0",
"profile": "XRechnung 3.0",
"rulesets": [
"schema-ubl",
"en16931-ubl",
"xrechnung-ubl"
],
"valid": true,
"summary": {
"errors": 0,
"warnings": 0,
"infos": 1
},
"reports": [
{
"ruleset": "schema-ubl",
"title": "XML Schema UBL 2.1",
"messages": []
},
{
"ruleset": "en16931-ubl",
"title": "EN 16931 (validation artefacts 1.3.17, UBL)",
"messages": []
},
{
"ruleset": "xrechnung-ubl",
"title": "XRechnung 3.0 (KoSIT-Schematron 2.6.0, UBL)",
"messages": [
{
"rule": "BR-DE-TMP-32",
"severity": "info",
"text": "Eine Rechnung sollte zur Angabe des Liefer-/Leistungsdatums entweder BT-72 \"Actual delivery date\", BG-14 \"Invoicing period\" oder in jeder Rechnungsposition BG-26 \"Invoice line period\" enthalten.",
"location": "/Invoice[1]"
}
]
}
],
"note": null,
"totalsCheck": [
{
"rule": "BR-CO-10",
"text": "Sum of invoice line net amount (BT-106) = sum of all line net amounts",
"expected": 314.86,
"actual": 314.86,
"ok": true
},
{
"rule": "BR-CO-13",
"text": "Invoice total amount without VAT (BT-109) = sum of lines − allowances + charges",
"expected": 314.86,
"actual": 314.86,
"ok": true
}
]
}
valid ist true, wenn keine Meldung die Schwere error hat. Auch
für ungültige Rechnungen kommt 200 – eine nicht bestandene Prüfung ist ein Ergebnis, kein
Fehler.
Als JSON auslesen
POST /v1/parse, dieselbe Rechnung, gekürzt auf einige Felder. Beträge und Daten bleiben
Zeichenketten genau wie in der Datei, damit durch Rundung nichts verloren geht:
{
"source": "xml",
"syntax": "UBL",
"profile": "XRechnung 3.0",
"invoice": {
"number": "123456XX",
"issueDate": "2016-04-04",
"typeCode": "380",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "[Seller name]",
"vatIdentifier": "DE 123456789",
"address": {
"city": "[Seller city]",
"postCode": "12345",
"countryCode": "DE"
}
},
"totals": {
"totalWithoutVat": "314.86",
"totalVatAmount": "22.04",
"totalWithVat": "336.9",
"amountDueForPayment": "336.9"
},
"lines": [
{
"quantity": "1",
"unitCode": "XPP",
"netAmount": "288.79",
"vatRate": "7",
"itemName": "Zeitschrift [...]",
"description": "Zeitschrift Inland"
}
]
},
"unmapped": []
}
XRechnung in ZUGFeRD umwandeln
POST /v1/convert?to=zugferd mit derselben XRechnung. Die Antwort nennt jede Änderung und
jeden Verlust und enthält die Prüfung des Ergebnisses; die Datei selbst steht in
document.base64 (hier weggelassen):
{
"target": "zugferd",
"changes": [
"Specification identifier (BT-24): urn:cen.eu:en16931:2017 instead of urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0"
],
"losses": [],
"ignoredAdditions": [],
"validation": {
"valid": true,
"summary": {
"errors": 0,
"warnings": 1,
"infos": 0
}
},
"document": {
"contentType": "application/xml",
"filename": "invoice_zugferd.xml"
}
}
Wenn Angaben fehlen
Eine XRechnung braucht Angaben, die einer ZUGFeRD-Rechnung fehlen können, etwa die Käuferreferenz
(Leitweg-ID), elektronische Adressen und einen Ansprechpartner des Verkäufers.
POST /v1/convert?to=xrechnung-ubl mit dem ZUGFeRD-PDF von oben antwortet mit
422 und nennt, was fehlt (gekürzt auf die ersten zwei von neun Feldern):
{
"error": {
"code": "additions_required",
"message": "The target format requires data the document does not contain. Nothing is invented: send it as \"additions\".",
"missing": [
{
"path": "buyerReference",
"name": "Buyer reference / Leitweg-ID",
"rule": "BR-DE-15",
"help": "For invoices to German public authorities the Leitweg-ID, otherwise the reference your customer gave you.",
"optional": false,
"provided": false
},
{
"path": "seller.electronicAddress",
"name": "Seller email address for invoices",
"rule": "PEPPOL-EN16931-R020",
"help": null,
"optional": false,
"provided": false
}
]
}
}
Schick die Werte als additions, mit path als Schlüssel, und wiederhole die
Anfrage. Vorhandene Angaben werden nie überschrieben; nicht benötigte Ergänzungen stehen in
ignoredAdditions.
{
"document": "<Base64>",
"to": "xrechnung-ubl",
"additions": {
"buyerReference": "04011000-12345-03",
"seller.electronicAddress": "rechnung@example.com",
"payment.iban": "DE02120300000000202051"
}
}
Fehler
Fehler kommen als JSON mit festem code und lesbarer message:
{"error": {"code": "not_an_e_invoice", "message": "…"}}
| Status | Code | Bedeutung |
|---|---|---|
| 400 | empty, bad_json, missing_document | Keine Datei, ungültiges JSON oder kein Feld document |
| 400 | invalid_target, invalid_lang, invalid_additions | Unbekanntes Zielformat oder unbekannte Sprache, Ergänzungen kein Objekt aus Zeichenketten |
| 401 | unauthorized | Anfrage kam nicht über RapidAPI |
| 404, 405 | not_found, method_not_allowed | Unbekannter Endpunkt oder falsche HTTP-Methode |
| 413 | too_large | Anfrage größer als 50 MB |
| 422 | not_an_e_invoice, not_readable | Weder UBL noch CII, oder ein PDF ohne eingebettete Rechnung |
| 422 | doctype_not_allowed | XML mit DOCTYPE- oder ENTITY-Deklaration wird aus Sicherheitsgründen abgelehnt |
| 422 | additions_required | Das Zielformat braucht Angaben – siehe missing |
| 422 | not_convertible, already_target_format | Umwandlung nicht möglich oder nicht nötig |
| 422 | result_not_valid | Die umgewandelte Rechnung besteht die offizielle Prüfung nicht und kommt deshalb nicht zurück (Bericht in validation) |
| 503, 504 | busy, timeout | Zu viele Anfragen gleichzeitig oder Bearbeitung länger als 30 s – später erneut versuchen |
| 500 | internal_error | Unser Fehler; nach den Abrechnungsregeln von RapidAPI zählen Antworten ab Status 500 nicht |
Regelwerke und Stände
| Regelwerk | Stand |
|---|---|
| XML-Schema | UBL 2.1, UN/CEFACT CII D16B |
| EN-16931-Prüfregeln (CEN) | 1.3.17 (UBL und CII) |
| XRechnung (KoSIT-Schematron) | XRechnung 3.0, Schematron 2.6.0 |
| ZUGFeRD / Factur-X | ZUGFeRD 2.5.2 / Factur-X 1.09.2, Profile MINIMUM, BASIC WL, BASIC, EN 16931, EXTENDED |
Rechnungen nach Peppol BIS Billing 3.0 werden gelesen und gegen EN 16931 geprüft. Erscheint ein neuer Stand eines Regelwerks, wird die API nachgezogen und diese Tabelle mit ihr.
Grenzen
- Anfragen bis 50 MB; nach 30 Sekunden wird die Bearbeitung abgebrochen.
- Anfragen je Monat und je Sekunde richten sich nach deinem Tarif bei RapidAPI.
- Ein gültiger Bericht heißt, dass die Rechnung die veröffentlichten Regeln erfüllt. Er ist keine Steuer- oder Rechtsberatung und garantiert nicht, dass ein Empfänger oder eine Behörde die Rechnung annimmt.
- Versand (Peppol, E-Mail) und elektronische Signaturen gehören nicht zur API.
Mit KI-Agenten (MCP)
RapidAPI stellt seine APIs auch als Werkzeuge für KI-Agenten über das Model Context Protocol (MCP) bereit. Mit deinem RapidAPI-Schlüssel kann ein Agent jeden Endpunkt als Werkzeug aufrufen; es gilt dein Tarif.
Datenschutz und Bedingungen
Rechnungen enthalten personenbezogene Daten. Wir verarbeiten sie nur, um deine Anfrage zu beantworten, im Arbeitsspeicher, und behalten nichts. Einzelheiten: Datenschutzhinweise der API und Auftragsverarbeitungsvertrag (Art. 28 DSGVO). Die Nutzungsbedingungen der API gelten zusätzlich zu den Bedingungen von RapidAPI.
Lizenzen
Die Prüfung nutzt die offiziellen Regelwerke und Open-Source-Bausteine unter ihren Lizenzen: die EN-16931-Artefakte des CEN und die XRechnung-Regeln der KoSIT (EUPL 1.2, Apache 2.0), die Factur-X-Regeln (Lizenz), SaxonJS (Copyright-Hinweis und Haftungsausschluss), xmllint-wasm, pdf-lib, fontkit, big.js und die DejaVu-Schriften.
Anbieter
Haag Automation, Julian Haag, Mühlstraße 35, 74360 Ilsfeld · julian@haag-automation.com · xmoo ist eine Marke von Haag Automation. Alle APIs