Referenz
Alle Angaben stammen aus dem tatsächlichen Server-Schema. Ein automatischer Test wacht darüber, dass diese Referenz nicht von der Implementierung abweicht.
Authentifizierung
Jeder Aufruf trägt den API-Schlüssel als Bearer-Token:
Authorization: Bearer flstr_live_…Der Mandant (das Konto) ergibt sich aus dem Schlüssel – niemals aus dem Request-Body. Ein Schlüssel sieht und schreibt ausschließlich Daten seines eigenen Kontos.
POST /api/v1/invoices
Erstellt eine Rechnung, schreibt sie fest (KoSIT-validiert, unveränderbar aufbewahrt, lückenlose Nummer) und gibt das ZUGFeRD zurück.
Request-Body
Pflichtfelder sind fett. Beträge sind ganzzahlige Cent (kein Komma, kein Float).
| Feld | Typ | Grenzen / Werte |
|---|---|---|
idempotencyKey | String | Pflicht, max. 255 Zeichen. Siehe Idempotenz. |
issueDate | String | Pflicht, YYYY-MM-DD (Rechnungsdatum). |
outputFormat | String | zugferd (Default) · xrechnung · pdf. |
deliveryDate | String | YYYY-MM-DD – Leistungsdatum. |
deliveryPeriod | Objekt | { "start": "YYYY-MM-DD", "end": "YYYY-MM-DD" } – Leistungszeitraum (statt deliveryDate). |
currency | String | 3 Zeichen, Default EUR. |
buyerReference | String | max. 255 – Käuferreferenz / Leitweg-ID (B2G). |
taxScheme | String | standard (Default) · kleinunternehmer · reverseCharge · taxExempt · intraCommunity · export. |
taxExemptionReason | String | max. 1000 – Befreiungsgrund (bei steuerfreien Fällen). |
taxExemptionReasonCode | String | max. 50 – z. B. VATEX-EU-AE. |
recipient | Objekt | Pflicht – der Empfänger, siehe unten. |
lines | Array | Pflicht, 1–1000 Positionen, siehe unten. |
paymentDueDate | String | YYYY-MM-DD – Fälligkeit. |
paymentTerms | String | max. 1000 – Zahlungsbedingungen (Text). |
skonto | Objekt | { "percent": 2, "days": 7, "basisAmountCents": 0 } (optional). |
notes | String[] | max. 20 Einträge à max. 1000 Zeichen. |
recipient (der Rechnungsempfänger):
| Feld | Typ | Grenzen |
|---|---|---|
name | String | Pflicht, max. 200. |
street | String | Pflicht, max. 200. |
postcode | String | Pflicht, max. 10. |
city | String | Pflicht, max. 100. |
countryCode | String | 2 Zeichen (Default DE). |
customerNumber | String | max. 50 – steuert den Kunden-Upsert. |
contactName | String | max. 200. |
vatId | String | max. 30 – USt-IdNr. (Pflicht bei reverseCharge/intraCommunity). |
email | String | max. 200. |
phone | String | max. 50. |
lines[] (je Position):
| Feld | Typ | Grenzen / Werte |
|---|---|---|
name | String | Pflicht, max. 400. |
quantity | Zahl | Pflicht (auch Dezimal, z. B. 2.5). |
unitCode | String | Pflicht – UN/ECE-Code: C62 Stück · HUR Stunde · DAY Tag · MON Monat · E49 Pauschale · KGM Kilogramm · MTR Meter · LTR Liter. |
unitPriceCents | Ganzzahl | Pflicht, ≥ 0 – Netto-Einzelpreis in Cent (z. B. 9000 = 90,00 €). |
vatCategory | String | Pflicht – S Regelsatz · AE Reverse Charge · K innergem. · G Ausfuhr · E steuerfrei/§19 · Z/O. |
vatRatePercent | Zahl | Pflicht, 0–100 (z. B. 19 oder 7). |
description | String | max. 1000. |
Unbekannte Zusatzfelder werden abgelehnt (400) – der Body wird streng geprüft. So kann z. B.
keine organizationId untergeschoben werden; der Mandant kommt immer aus dem Schlüssel.
Response (201 = neu · 200 = idempotente Wiederholung)
{
"invoiceNumber": "RE-2026-1",
"invoiceId": "…",
"status": "finalized",
"idempotent": false,
"idempotencyMismatch": false,
"customer": { "number": "K-100", "apiCreated": true, "apiUpdated": false },
"documents": {
"xml": { "base64": "…", "filename": "RE-2026-1.xml", "contentType": "application/xml" },
"pdf": { "base64": "…", "filename": "RE-2026-1.pdf", "contentType": "application/pdf" }
}
}| Feld | Bedeutung |
|---|---|
invoiceNumber | Die vergebene, lückenlose Rechnungsnummer. |
invoiceId | Die ID für den späteren GET-Abruf. |
status | Immer finalized (festgeschrieben). |
idempotent | true, wenn dieser Aufruf eine Wiederholung mit bekanntem Schlüssel war (dieselbe Rechnung, nicht neu erzeugt). |
idempotencyMismatch | Nur true, wenn derselbe Schlüssel mit abweichenden Daten kam (die bestehende Rechnung wird zurückgegeben, die neuen Daten ignoriert). |
customer | null, wenn keine customerNumber übergeben wurde; sonst { number, apiCreated, apiUpdated } – siehe Kunden-Upsert. |
documents.xml | Das maßgebliche CII-XML (immer vorhanden). |
documents.pdf | Das PDF/A-3 – null bei outputFormat: "xrechnung" (XML-only). |
Statuscodes
| Code | Bedeutung |
|---|---|
| 201 | Rechnung erstellt + festgeschrieben. |
| 200 | Idempotente Wiederholung (dieselbe Rechnung). |
| 400 | Ungültige Daten / ungültiges JSON / idempotencyKey fehlt. |
| 401 | Schlüssel ungültig, widerrufen oder abgelaufen. |
| 403 | Tarif zu niedrig (Basic nötig) oder Schlüssel vom Betreiber gesperrt. |
| 422 | KoSIT-Validierung fehlgeschlagen (kosit_validation) oder Vorbedingung fehlt, z. B. kein Unternehmensprofil (invalid_state). |
| 429 | rate_limit (Anfrage-Limit – kurz warten, wiederholen) oder daily_cap (Tages-Limit – nicht wiederholen). |
| 503 | Rate-Limiter vorübergehend nicht verfügbar. |
Details zu jedem Code: Fehler. Jede Fehlerantwort trägt ein
Feld error (Maschinen-Code) und message (Klartext); interne Details werden nie ausgegeben.
GET /api/v1/invoices/{id}
Holt die festgeschriebene Datei erneut. Query ?type=pdf (Default) oder ?type=xml.
curl "https://e-rechnung.flstr.de/api/v1/invoices/6f1c…?type=xml" \
-H "Authorization: Bearer flstr_live_DEIN_SCHLUESSEL" -o rechnung.xmlDie Antwort ist die Datei selbst (nicht JSON): Content-Type: application/pdf bzw.
application/xml, als Download-Anhang. Ein Schlüssel kann nur Belege seines eigenen Kontos
abrufen – fremde/unbekannte IDs ergeben 404. Bei outputFormat: "xrechnung" gibt es kein PDF,
nur ?type=xml.