Automatic retries
The SDKs retry only on responses that are safe to retry: HTTP 429 and 5xx. Every other failure - including 4xx other than 429 - is surfaced to your code immediately, with no retry. See Errors for the typed error shape and the codes worth branching on. Retries use full-jitter exponential backoff: a base delay of 500ms, a cap of 10s, and a random delay drawn between zero and the current ceiling on each attempt. When the response carries aRetry-After header, it is honored instead
and clamped to the range [0, 300s].
By default the SDKs allow maxRetries: 2 - up to 3 total attempts - and
apply no per-request timeout. Both are configurable; see
Configuration.
Backoff illustration
With the defaults (base 500ms, cap 10s,maxRetries: 2), a request that keeps
receiving 429/5xx is delayed within these windows before each retry. The actual
delay is a uniform random pick inside the window (full jitter):
| Attempt | Retry | Delay window |
|---|---|---|
| 1 | initial request | none |
| 2 | first retry | 0 - 500ms |
| 3 | second retry | 0 - 1000ms |
500ms, 1s, 2s, …) until it reaches the
10s cap, then stays there. A Retry-After header, when present, overrides the
computed window for that attempt.
Idempotency
Every write accepts anIdempotency-Key header, a UUIDv4. The SDKs generate
one automatically for each write; you may also supply your own - persist it
alongside the operation so a retry after a crash reuses the same key and the
server replays the original response instead of acting again.
Reusing a key with a different request body is a conflict: the API returns
409 IDEMPOTENCY_KEY_REUSED.
These endpoints support idempotency:
| Endpoint | Operation |
|---|---|
POST /v1/auth/exchange | Exchange credentials for a member token. |
POST /v1/redemptions | Redeem an offer. |
POST /v1/wallet/credit | Credit points to a wallet. |
POST /v1/webhooks | Register a webhook endpoint. |
curl
Idempotency on {id} routes
The OpenAPI emitter drops the Idempotency-Key header from the API reference for
routes with a path parameter - for example POST /v1/conversations/{id}/messages.
This is a documentation-only limitation: idempotency is still fully supported on
those routes. The SDKs continue to send the header automatically, and when you
call such an endpoint directly you should set the header yourself.
Absence of
Idempotency-Key from the reference for an {id} route does not
mean the route ignores it. Send the header; reusing it with a different body
still returns 409 IDEMPOTENCY_KEY_REUSED.Related
Errors
The typed error taxonomy and the stable codes worth handling.
Configuration
Tune
maxRetries, timeouts, and the rest of the client options.