Idempotenz
Der wichtigste Abschnitt dieser Doku. Ein falsch gesetzter Idempotenz-Schlüssel ist der eine Fehler, den Ausprobieren nicht aufdeckt: Es funktioniert scheinbar – bis in der echten Belegkette stille Doppel-Rechnungen auftauchen. Lesen Sie das einmal ganz.
Warum es Idempotenz gibt
Eine festgeschriebene Rechnung ist unveränderbar und trägt eine lückenlose Nummer. Sie darf
nie doppelt entstehen. Netzwerke sind aber unzuverlässig, und Auslöser (z. B. Zahlungs-Webhooks)
werden mehrfach zugestellt. Der idempotencyKey sorgt dafür, dass derselbe Vorgang – egal
wie oft er ankommt – genau eine Rechnung erzeugt.
Die Regeln
- Der
idempotencyKeyist Pflicht. Fehlt er, antwortet die API mit 400. - Er muss pro Geschäftsvorfall (Bestellung / Zahlung) eindeutig und stabil sein – über alle Wiederholungen desselben Vorgangs hinweg derselbe Wert.
- Gleicher Schlüssel → dieselbe Rechnung zurück (
idempotent: true), kein Duplikat, kein Fehler. - Gleicher Schlüssel, andere Daten → die bestehende Rechnung wird zurückgegeben, die neuen
Daten werden ignoriert; die Antwort trägt
idempotencyMismatch: trueals Hinweis.
⭐ Das konkrete Muster
Nehmen Sie eine ID, die den Geschäftsvorfall bereits eindeutig identifiziert – die
Stripe-Payment-ID (pi_…) oder Ihre eigene Bestell-/Auftragsnummer. Dann sind
Wiederholungen automatisch sicher.
Typischer Flow: Ihr Stripe-Webhook meldet „Zahlung erfolgreich” → Sie rufen die flstr-API auf. Stripe stellt Webhooks mehrfach zu (Retries, Netzwerk). Mit der Payment-ID als Schlüssel erzeugt jede Wiederholung dieselbe Rechnung:
{
"idempotencyKey": "pi_3QabcXYZ...", // die Stripe-Payment-ID – stabil pro Zahlung
"issueDate": "2026-05-02",
"recipient": { "name": "…", "street": "…", "postcode": "…", "city": "…" },
"lines": [ { "name": "…", "quantity": 1, "unitCode": "C62",
"unitPriceCents": 5000, "vatCategory": "S", "vatRatePercent": 19 } ]
}- 1. Zustellung →
201, RechnungRE-2026-1erstellt. - 2./3. Zustellung (Webhook-Retry, gleicher Key) →
200, dieselbeRE-2026-1,idempotent: true. Kein Duplikat.
⚠️ Was Sie nicht tun dürfen
Kein zufälliger Schlüssel pro Request. Ein randomUUID() oder Zeitstempel je Aufruf macht jede
Wiederholung „neu” – und erzeugt bei jedem Retry eine weitere echte Rechnung. Weil
festgeschriebene Rechnungen unveränderbar sind, lassen sich diese Duplikate nicht einfach löschen.
// FALSCH – erzeugt bei jedem Webhook-Retry ein Duplikat:
{ "idempotencyKey": "a1b2c3-random-jedes-mal-neu", ... }
// RICHTIG – stabil pro Vorgang:
{ "idempotencyKey": "pi_3QabcXYZ...", ... }Kurz gefasst
| Situation | Verhalten |
|---|---|
| Neuer Schlüssel | Neue Rechnung, 201, idempotent: false. |
| Gleicher Schlüssel, gleiche Daten | Dieselbe Rechnung, 200, idempotent: true. |
| Gleicher Schlüssel, andere Daten | Dieselbe (bestehende) Rechnung, idempotencyMismatch: true; neue Daten ignoriert. |
| Kein Schlüssel | 400. |