The problem
Your POST to/api/v1/leads:bulk timed out. Did we receive it?
Retrying naively could double-insert. Retrying with an idempotency
key lets us recognize the retry and return the original response.
How it’ll work
Send a unique header on write endpoints:(tenant_id, key) for 24 hours. Retries with the
same key within that window return the original response (same
HTTP status, same body).
Generating keys
Use a UUID v4 per logical operation. The operation, not the attempt: if attempt 2 has a different key than attempt 1, we treat them as independent requests.Python
Idempotency vs webhook event_id
Two separate ideas that solve opposite-direction problems:| Concept | Direction | Dedup key |
|---|---|---|
Idempotency-Key | Your client → our API | You pick a UUID per logical write |
event_id | Our webhooks → your endpoint | We pick a UUID per logical event |
Works on which endpoints
AllPOST / PUT / PATCH on /api/v1/* once shipped. GET /
HEAD / DELETE don’t need it (already idempotent by HTTP semantics,
modulo DELETE being “at most once” — we return 204 whether or not
the resource previously existed).