Skip to Content

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 idempotencyKey ist 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: true als 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. Zustellung201, Rechnung RE-2026-1 erstellt.
  • 2./3. Zustellung (Webhook-Retry, gleicher Key) → 200, dieselbe RE-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

SituationVerhalten
Neuer SchlüsselNeue Rechnung, 201, idempotent: false.
Gleicher Schlüssel, gleiche DatenDieselbe Rechnung, 200, idempotent: true.
Gleicher Schlüssel, andere DatenDieselbe (bestehende) Rechnung, idempotencyMismatch: true; neue Daten ignoriert.
Kein Schlüssel400.