Idempotency
Network failures, timeouts, and process crashes are unavoidable. Aeses supports idempotency keys so that retrying a POST is safe — the same logical request only takes effect once, no matter how many times you retry.
Sending an idempotency key
Add the Idempotency-Key header to any POST request. The value can be any string up to 255 characters; a UUID v4 is a good default.
curl https://api.aeses.io/v1/deposits \
-H "x-api-key: sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"asset": "USDT",
"chain": "ethereum"
}'The first response is stored for 24 hours. Subsequent requests with the same key and the same body return the original response — including the original status code — without performing the operation again.
Where to use it
We strongly recommend sending an idempotency key on every POST. It is required in practice for:
POST /v1/deposits— avoids generating multiple addresses on retry.POST /v1/withdrawals— prevents double-spending if your client retries.POST /v1/charges— prevents creating duplicate payment intents.POST /v1/webhook-deliveries/:id/replay— re-delivery is naturally idempotent, but a key prevents accidental floods.
GET and DELETE are naturally idempotent and do not require a key.
Generating keys
Generate a key once per logical operation, before the first attempt. Persist it alongside the operation in your database, and reuse it on every retry until the operation succeeds. A common pattern:
operation_id = uuid4()
save(state="pending", idempotency_key=operation_id)
while not done:
try:
response = api.create_deposit(..., idempotency_key=operation_id)
save(state="confirmed", deposit_id=response.id)
done = True
except RetryableError:
sleep(backoff())
Never generate a fresh key inside the retry loop — that defeats the purpose.
Replay behavior
The replayed response is byte-identical to the original, including any error response. If the original request returned 400 invalid_request_error, the same 400 is replayed; no business state changes.
The original Request-Id is preserved on replays for auditability. The HTTP response additionally includes:
Idempotency-Replayed: true— present when the response is served from cache.
Conflicts
If you reuse the same key with a different request body, Aeses returns 409 idempotency_key_reused:
{
"error": {
"type": "idempotency_error",
"code": "idempotency_key_reused",
"message": "Idempotency-Key already used with a different request payload.",
"request_id": "req_01HXYZ..."
}
}This usually indicates a bug in your client: the key was reused for an unrelated operation. Generate a fresh key for each new logical operation.
TTL
Idempotency records expire 24 hours after the original request. After that, the same key can be reused for a new operation without conflict. If you retry beyond the 24-hour window, the request is processed as if it were new — design retries to complete well within this window.