Idempotency
Esta página aún no está disponible en tu idioma.
Idempotency
Section titled “Idempotency”Write routes that create a resource (for example, creating a webhook endpoint, sending a test webhook event, or uploading to the knowledge base) require an Idempotency-Key header. It lets you safely retry a request — after a timeout, a dropped connection, anything — without risking a duplicate side effect.
POST /api/v1/webhooksIdempotency-Key: 7d6f0a2e-8b1c-4a3d-9e5f-2c1b0a3d4e5fContent-Type: application/json
{ "url": "https://example.com/hooks/clienta", "events": ["conversation.created"] }Use a fresh, unique key (a UUID is fine) per logical operation, and reuse the same key when retrying that same operation.
How it works
Section titled “How it works”Requests are claimed first, before any work happens — this is what makes it crash-safe, not just retry-safe:
- Your request arrives with an
Idempotency-Key. The server tries to atomically claim(organization, key, route, idempotencyKey). - If nothing else has claimed that combination yet, you win the claim and the request proceeds normally.
- If it’s already claimed, the server looks at what happened to the earlier attempt and responds accordingly — see the table below.
| Situation | Response |
|---|---|
| Same key, identical request, already completed | The original response is replayed verbatim (same status code and body) |
| Same key, but a different request body/method/path | 409 IDEMPOTENCY_KEY_REUSED |
| Same key, an earlier attempt is still in flight | 425 IDEMPOTENCY_IN_PROGRESS with a Retry-After header |
| Same key, an earlier attempt crashed mid-request (its processing lease expired) | The claim is safely reclaimed and the request is retried server-side |
No Idempotency-Key header on a route that requires one | 400 IDEMPOTENCY_KEY_REQUIRED |
Record lifetime
Section titled “Record lifetime”- A processing claim is held under a short lease (long enough to comfortably cover one request, including any database work) — if the process handling it crashes, another attempt with the same key safely takes over once the lease expires, instead of returning
425forever. - A completed record — and its cached response — is retained for 24 hours, matching how long we’ll honor a retry with the same key. After that window, reusing the same key starts a brand-new operation.
An idempotency key is scoped to your key/identity + the specific route — the same Idempotency-Key value used against two different routes, or by two different API keys, never collides.