Skip to content

Idempotency & revisions

Idempotency & revisions

Why retrying after a network error is safe and how concurrent changes never overwrite each other.

One key, four outcomes

Idempotency-Key is required for POST and DELETE and lasts 24 hours per key, method and route. Only status and resource ids are stored, never a response body.
  • 201First callBodo runs it and stores status and ids.
  • 201 · replaySame key, same bodyThe answer is rendered again under your current scope, with Idempotent-Replayed: true.
  • 409The first call is still runningWait briefly and retry with the same key.IDEMPOTENCY_IN_PROGRESS
  • 422Same key, different bodyBodo runs nothing. Create a new key for a new operation.IDEMPOTENCY_PAYLOAD_MISMATCH
Answers with 5xx, 429 and 503 are never stored. You can simply retry with the same key.

Revisions instead of overwriting

Contacts, companies, tasks and documents carry a revision. The ETag is "r<revision>", If-Match is optional. The comparison runs atomically in the database, not in the gateway.
Two writers, one revision
GET /v1/contacts/con_4Nf7…        → 200, ETag: "r3"

PATCH /v1/contacts/con_4Nf7…
If-Match: "r3"
Content-Type: application/merge-patch+json
{"email": "e.mustermann@musterfirma.de"}
                                  → 200, ETag: "r4"

PATCH … If-Match: "r3"            → 412 PRECONDITION_FAILED

On PRECONDITION_FAILED read the record again, merge your change onto it and send it with the new ETag.

PATCH as JSON Merge Patch

RFC 7396, with Content-Type: application/merge-patch+json.
You sendEffect
a field with a valuesets the value
a field with nullclears the value
an arrayreplaces the whole array
a missing fieldstays unchanged