xml-invoice.io Funktionen Preise Dokumentation Docker
API-Dokumentation

Endpoints

Dreizehn Endpoints in vier Gruppen: Erzeugung und Validierung, Journal, Übergabe an die Buchhaltung und Share-Links.

Alle Pfade relativ zu https://api.xml-invoice.io  ·  Authentifizierung und Credits: siehe Einstieg

EndpointFunktionCredits
POST /v2/assessmentRechnung validieren, optional archivierenmit archive
POST /v2/invoice/xmlXRechnung, Peppol oder EN 16931 erzeugenmit archive
POST /v2/invoice/zugferdZUGFeRD-PDF erzeugenmit archive
POST /v2/invoice/pdfRechnung als PDF rendernnein
GET /v2/invoicesJournal, gefiltert und paginiertnein
GET /v2/invoice/{kennung}Einzelne Rechnung mit allen Angabennein
PUT /v2/invoice/{kennung}Buchung, Zahlung, Abweisungnein
DELETE /v2/invoice/{kennung}Aus der Ansicht entfernennein
GET /v2/invoice/preview/{nummer}Arbeitsbeleg als PDFnein
POST /v2/exportÜbergabe an die Buchhaltung anlegenja
GET /v2/export/{nummer}Übergabepaket als ZIPnein
GET /v2/exportsListe der Übergaben, neueste zuerstnein
GET /v2/s3/share/{token}Geteiltes Dokument, ohne Authentifizierungnein

Validieren

POST /v2/assessment

Request-Body: Rechnung als XML (CII oder UBL) oder ZUGFeRD-PDF; beim PDF wird das eingebettete XML extrahiert. Validiert wird mit dem KoSIT-Validator gegen das Regelwerk, das die Rechnung angibt: EN 16931, XRechnung oder Peppol BIS Billing.

ParameterWerteBedeutung
archivetrue · false Default false. Mit true wird eine gültige Rechnung archiviert, erhält eine Belegnummer und kostet einen Credit. Ungültige Rechnungen werden nicht archiviert und kosten nichts.
directionincoming · outgoing Eingang oder Ausgang im Journal. Default incoming. Für eigene Ausgangsrechnungen outgoing setzen, sonst erscheinen sie im Journal als Eingang.
{
  "valid": false,
  "assessment": "reject",
  "format": "CII",
  "standard": "XRechnung",
  "errorCount": 2,
  "warningCount": 0,
  "messages": [
    { "level": "error", "message": "[BR-DE-15] Die Leitweg-ID ist nicht angegeben." }
  ],
  "document": null,
  "credits": { "used": 13, "limit": 120, "remaining": 107 }
}

valid ist das Ergebnis, assessment die Empfehlung des Validators (accept, reject oder unsupported), messages enthält jede Meldung mit ihrem level. Die Texte stammen vom Validator und sind auf Deutsch.

Bei Archivierung enthält document den Beleg:

"document": {
  "documentNumber": "BEL-2026-00042",
  "invoiceUrl": "https://api.xml-invoice.io/v2/s3/share/29dd3a9d…",
  "invoiceUrlExpiresAt": "2026-10-27T07:15:58+02:00",
  "reportUrl": "https://api.xml-invoice.io/v2/s3/share/4b3ca11a…",
  "reportUrlExpiresAt": "2026-10-27T07:15:58+02:00",
  "duplicateOf": null
}

reportUrl verweist auf den vollständigen KoSIT-Prüfbericht als XML, das maschinenlesbare Original. Er wird mit der Rechnung archiviert und bleibt für die gesamte Aufbewahrungsfrist abrufbar.

Duplikate Bei byteweise identischem Inhalt antwortet die API mit 409 conflict und archiviert nichts. Dieselbe Rechnungsnummer vom selben Absender mit anderem Inhalt kann eine Korrektur sein: Sie wird archiviert, document.duplicateOf verweist auf die erste Fassung.

Erzeugen

Beide Endpoints erwarten Rechnungsdaten als JSON mit den Business Terms der EN 16931 als Schlüssel (BT-1, BT-44, …). Die Pflichtfelder beschreibt die Übersicht auf xml-rechnung.eu.

Alle Business Terms der Norm werden unterstützt, darunter Nachlässe und Zuschläge auf Dokument- und Positionsebene, Steuervertreter, SEPA-Mandat, Anlagen, Bruttopreis mit Preisnachlass, Artikelkennungen und -merkmale sowie Fremdwährung für die Steuer. Drei Ausnahmen sind unten beschrieben.

Nach der Erzeugung wird validiert: Die Response enthält dasselbe Prüfergebnis wie oben und das Dokument.

Schlüsselformat

Ein flaches Objekt ohne Verschachtelung. Wiederholte Gruppen (Positionen, Steueraufschlüsselungen, Nachlässe, Zuschläge, Anlagen) werden mit # und der Nummer des Vorkommens adressiert:

{
  "BT-1":      "R-2026-0042",
  "BT-27":     "Muster GmbH",

  "BT-153#1":  "Beratungsleistung",
  "BT-131#1":  "1490.00",
  "BT-136#1":  "10.00",

  "BT-153#2":  "Software-Lizenz",
  "BT-131#2":  "500.00",

  "BT-92#1":   "20.00",
  "BT-97#1":   "Treuerabatt",

  "BT-118#1":  "S",
  "BT-119#1":  "19"
}
SchlüsselBedeutung
BT-27Einmalige Angabe.
BT-153#2Bei Positionsfeldern ist das Vorkommen die Zeile: der Artikel der zweiten Position.
BT-136#2Der Nachlass dieser Zeile. Je Zeile sind ein Nachlass und ein Zuschlag möglich.
BT-92#2Auf Dokumentebene ist das Vorkommen die Zählung in der Gruppe: der zweite Nachlass.
BT-92Ohne # gilt das erste Vorkommen. Bei genau einem Rabatt ist keine Zählung nötig.

Bei vier Kennungen ist das Schema in der Norm ein eigener Business Term (BT-18, BT-128, BT-157, BT-158). Im flachen Schlüssel steht es vor einem Doppelpunkt, wie bei der elektronischen Adresse: "BT-157#1": "0160:04012345678901".

Drei nicht unterstützte Business Terms BT-87 und BT-88, Kartennummer und Karteninhaber: Eine Kartennummer läge acht Jahre im Archiv, und bisher gab es keine Nachfrage nach dem Feld. Außerdem BT-125, das eingebettete Dokument als base64: Ein PDF darin überschreitet das Body-Limit, und die Response enthielte es ein zweites Mal. BT-122 bis BT-124 (Kennung, Beschreibung, externer Verweis) werden unterstützt. BT-125 wird beim Lesen weiterhin ausgewertet und erscheint im Journal. BT-24 wird aus cius gesetzt, nicht aus dem Request.
Fünf häufige Validierungsfehler Keiner davon ist ein Fehler der API, aber jeder führt zu einer abgewiesenen Rechnung. Alle sind beim Erstellen unserer Testrechnungen aufgetreten. Elektronische Adresse (BT-34, BT-49): erfordert ein Schema aus der EAS-Liste; EM: für E-Mail ist dort nicht enthalten, eine GLN ist 0088:…. Das Schema ist Pflicht, ohne es lehnt der Validator die Rechnung ab (BR-62, BR-63). Bei Werten im E-Mail-Format setzen wir EM; für alle anderen, etwa eine GLN, setzen wir kein Schema, und der Validator meldet BR-62. Das Attribut bestimmt den Zustellweg beim Empfänger, deshalb wird es nicht geraten. Basisbetrag ohne Prozentsatz: BT-93 erfordert BT-94, BT-100 erfordert BT-101. Schema einer Objektkennung: muss ein UNTDID-1153-Code sein. Summen werden nicht nachgerechnet: BT-106 bis BT-115 kommen aus Ihrem Request; ob sie zu Positionen, Nachlässen und Zuschlägen passen, prüft erst der Validator. Ein Nachlass auf Dokumentebene wirkt sich auf fünf Summen aus. BT-8 nutzt je Syntax eine andere Codeliste: Der Steuerzeitpunkt als Code ist in CII 5 für das Rechnungsdatum (UNTDID 2475), in UBL 3 (UNTDID 2005), außerdem 29/35 für das Lieferdatum und 72/432 für das Zahldatum. Die API rechnet das nicht um, weil ein ausgetauschter Wert eine Angabe wäre, die Sie nicht gemacht haben. Für beide Syntaxen BT-8 je Request passend setzen oder das syntaxneutrale Datum BT-7 verwenden.

POST /v2/invoice/xml

ParameterWerteBedeutung
formatcii · ublSyntax. Default cii.
ciusen16931 · xrechnung · peppolRegelwerk. Default en16931. peppol erfordert format=ubl, da Peppol BIS eine CIUS auf UBL ist.
archivetrue · falseArchivieren und abrechnen. Default false.
directionincoming · outgoing Richtung im Journal. Default outgoing.

POST /v2/invoice/zugferd

PDF mit eingebettetem XML, lesbar für Menschen und maschinell verarbeitbar. cius unterstützt hier en16931 und xrechnung; Peppol nicht, da das Profil einen Transportweg beschreibt und kein anhängbares Dokument. Dazu template für das Layout sowie archive und direction mit denselben Werten und Defaults wie oben.

Das erzeugte Dokument steht im Response-Body, nicht als separate Datei:

"invoice": {
  "contentType": "application/pdf",
  "encoding": "base64",
  "content": "JVBERi0xLjQKJeLjz9MK…"
}

encoding ist utf-8 beim XML (das Dokument steht direkt im Feld) und base64 beim PDF. So enthalten Prüfergebnis, Belegnummer und Credit-Stand dieselbe Response.

POST /v2/invoice/pdf

Rendert eine fertige Rechnung: XML oder ZUGFeRD-PDF als Input, PDF als Output. Keine Validierung, keine Archivierung, keine Credits. template wählt das Layout: default, readable, din5008, arbeitsbeleg. Der Response-Body ist das PDF; Metadaten stehen in den Headern X-Invoice-Format, X-Invoice-Standard und X-Invoice-SHA256.

Journal

GET /v2/invoices

Alle archivierten Rechnungen, gefiltert, sortiert und paginiert.

ParameterWerteBedeutung
view open · unpaid · paid · exported · rejected · all Ansicht. open ist die Arbeitsliste: weder bezahlt noch abgewiesen noch übergeben. unpaid liefert alle offenen Zahlungen, auch für bereits übergebene Rechnungen.
exportabletrue · false Zur Übergabe bereit: weder abgewiesen noch bereits übergeben.
directionincoming · outgoingEingang oder Ausgang.
from, toJJJJ-MM-TTZeitraum der Archivierung. to ist inklusive.
searchTextVolltextsuche in Belegnummer, Rechnungsnummer, Absender, Empfänger und Betrag.
sort createdAt · updatedAt · documentNumber · invoiceDate · invoiceNumber · sellerName · buyerName · paidAt Default -createdAt. Ein Minus kehrt die Sortierung um.
page, limitZahl, limit bis 100Default Seite 1 mit 50 Einträgen.
{
  "invoices": [ … ],
  "pagination": { "page": 1, "limit": 50, "total": 231, "pages": 5 }
}

Unbekannte Werte führen zu 400, nicht zu einer stillschweigend anderen Sortierung. Die Liste enthält keine Share-Links, da sonst für jede Zeile ein neuer erzeugt würde. Share-Links liefert der Abruf eines einzelnen Belegs.

GET /v2/invoice/{kennung}

Als Kennung gilt die Belegnummer (BEL-2026-00042) oder die ID aus der Liste.

Die Response enthält die Stammdaten der Rechnung (meta), alle Business Terms (businessTerms), das Prüfergebnis (validation), die Buchungsangaben (accounting), die Zeitpunkte für Zahlung, Abweisung und Übergabe, die Historie (history) und die Aufbewahrungsfrist expiresAt nach § 147 Abs. 4 AO. Dazu die Share-Links invoiceUrl und reportUrl.

PUT /v2/invoice/{kennung}

Partielles Update: Nur die übergebenen Felder werden geändert.

{
  "paidAt": "2026-10-20",
  "accounting": { "debitAccount": "6300", "costCenter": "Werkstatt", "note": "Teilzahlung" },
  "direction": "incoming",
  "rejected": false
}

paidAt ist das Datum auf dem Kontoauszug, nicht das Datum der Erfassung; null entfernt den Vermerk. rejected weist die Rechnung ab: Sie bleibt im Archiv, wird aber nicht an die Buchhaltung übergeben. Auch das ist umkehrbar.

Bezahlt und abgewiesen schließen sich aus, beides zugleich führt zu 409. Dasselbe gilt nach der Übergabe: Gebuchte Angaben lassen sich nicht mehr ändern.

DELETE /v2/invoice/{kennung}

Response 204. Die Rechnung verschwindet aus Liste und Einzelansicht, ausgegebene Share-Links werden widerrufen. Der Datensatz bleibt erhalten, da die achtjährige Aufbewahrungsfrist weiter gilt.

GET /v2/invoice/preview/{nummer}

Arbeitsbeleg einer archivierten Rechnung als PDF für die Anzeige im Browser. Nur dieser Endpoint enthält Belegnummer, Archivierungszeitpunkt und Datenformat auf dem Beleg.

Übergabe an die Buchhaltung

POST /v2/export

Bündelt Rechnungen zu einer Übergabe mit Nummer, Belegliste als CSV und den Belegen. Request-Body: Kennungen oder Belegnummern, auch gemischt:

{ "invoiceIds": ["BEL-2026-00041", "BEL-2026-00042"] }

Response 201 mit der Übergabe. documentListUrl ist der Share-Link zur Belegliste und kann direkt an die Kanzlei gehen:

{
  "export": {
    "number": "UEB-2026-0007",
    "invoiceCount": 2,
    "documentNumbers": ["BEL-2026-00041", "BEL-2026-00042"],
    "skipped": [],
    "documentListUrl": "https://api.xml-invoice.io/v2/s3/share/2faa4036…",
    "createdAt": "2026-10-20T07:16:38+02:00"
  },
  "credits": { "used": 14, "limit": 120, "remaining": 106 }
}

Abgewiesene und bereits übergebene Rechnungen werden übersprungen und in skipped aufgeführt. Ist keine Rechnung übergebbar, antwortet die API mit 404 und einer Begründung statt mit einer leeren Übergabe. Der Credit wird für die Belegliste berechnet, das einzige neu erzeugte Dokument.

format unterstützt derzeit nur zip (Default). Andere Werte führen zu einem Fehler statt zu einer stillschweigenden Annahme.

GET /v2/export/{nummer}

Übergabepaket als ZIP: die Belege unter ihren Dateinamen und die Belegliste im ursprünglichen Stand. Sie wird nicht neu berechnet, da sie als Nachweis dient. Fehlt ein Original im Archiv, schlägt der Request nicht fehl; betroffene Rechnungen stehen im Header X-Skipped-Invoices.

GET /v2/exports

Liste der Übergaben, neueste zuerst, mit page und limit (Default 25). Ohne Share-Links; das Paket liefert der Endpoint oben.

Share-Links

GET /v2/s3/share/{token}

Liefert das Dokument hinter einem Share-Link, ohne Authentifizierung, sieben Tage gültig. Die URL steht fertig in invoiceUrl, reportUrl und documentListUrl. Der Token in der URL ist der Schlüssel: Geben Sie den Link nur an berechtigte Empfänger weiter.

Weiterlesen

Einstieg

Authentifizierung, Credits, Fehlerformat und Limits für alle Endpoints.

Business Terms

Pflichtfelder nach EN 16931 und die Bedeutung der Codes.

API-Zugang mit kostenlosem Konto.

Konto, Token und Credits gelten auch in der Anwendung xml-rechnung.eu. Zum Start gibt es 10 Credits. Der API-Zugang gehört zum Abo Plus, 12,00 € im Monat.