# Idempotenz

Netzwerke sind unzuverlässig. Bekommst du auf eine Anfrage keine Antwort, sollst du sie einfach wiederholen können, ohne doppelte Kalender oder Termine zu erzeugen.

## Termine: von Haus aus idempotent

- **`PUT` auf einen Termin** schreibt den Termin unter deiner `external_id`. Doppelt geschickt ergibt das denselben Termin. Ist nichts anders als vorher, kommt `"changed": false`, und nichts wird geschrieben.
- **`DELETE` auf einen Termin** antwortet immer `204`, auch wenn der Termin schon gelöscht war.
- **Batch** besteht aus `PUT` und `DELETE` und lässt sich deshalb ebenfalls komplett wiederholen.

## Kalender anlegen: `Idempotency-Key`

`POST /v1/publisher/calendars` legt bei jedem Aufruf einen neuen Kalender an. Schick deshalb einen eindeutigen Header mit, zum Beispiel eine UUID:

```bash
curl https://api.kalender-sync.de/v1/publisher/calendars \
  -H "Authorization: Bearer $KS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3b0f6a52-6a1e-4c55-9d1b-0a7f2c9e1d44" \
  -d '{ "name": "Riverside Yoga", "timezone": "Europe/Berlin" }'
```

- Wiederholst du **dieselbe Anfrage mit demselben Key** innerhalb von 24 Stunden, bekommst du die gespeicherte Antwort des ersten Aufrufs zurück, mit dem Header `Idempotent-Replayed: true`. Es entsteht kein zweiter Kalender.
- Derselbe Key mit **einer anderen Anfrage** (anderer Body oder Pfad) ergibt `409` [`idempotency_key_reused`](https://docs.kalender-sync.de/api/errors/idempotency_key_reused/).
- Läuft die erste Anfrage noch, ergibt eine Wiederholung `409` [`idempotency_in_progress`](https://docs.kalender-sync.de/api/errors/idempotency_in_progress/). Warte kurz und versuche es erneut.
- Ist die erste Anfrage mit einem Fehler gescheitert, wird nichts gespeichert. Die Wiederholung läuft dann ganz normal.
- Der Key darf bis zu 255 Zeichen lang sein, sonst `400` [`invalid_idempotency_key`](https://docs.kalender-sync.de/api/errors/invalid_idempotency_key/). Er gilt pro API-Key.

## Optimistisches Sperren

Willst du verhindern, dass zwei Systeme sich gegenseitig überschreiben, schick bei `PUT` auf einen Termin den Header `If-Match` mit der zuletzt gesehenen `sequence`. → [Termine: If-Match](https://docs.kalender-sync.de/api/events/#optimistisches-sperren-mit-if-match)