Idempotency
Billable endpoints accept an optional Idempotency-Key header so retries — caused by a network blip, a load-balancer timeout, a client crash — won't be charged twice.
How It Works
When you send a request with an Idempotency-Key header, the server stores the mapping (your user, key) → jobId the first time it sees the pair. Any subsequent request that arrives with the same key, from the same account, returns the original jobId without:
- enqueueing a new analysis job
- freezing additional tokens
- starting a duplicate run
The key is scoped to your account, so two different users can pick the same key without colliding.
First request: Idempotency-Key: 7b4d… → 202 Accepted { jobId: A, status: "queued" }
Retry: Idempotency-Key: 7b4d… → 200 OK { jobId: A, status: "duplicate" }
The status: "duplicate" field lets you distinguish a fresh enqueue from a replayed one if you need to.
Usage
Send any unique string (UUID v4 is a good default) in the Idempotency-Key header:
curl -H "X-API-Key: ak_live_your_key_here" \
-H "Idempotency-Key: 7b4d8e2c-1a3f-4f1e-9b6a-5d0e8c2a7b91" \
"https://mvp.amlyou.com/api/analysis/0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18?network=ethereum"
The header applies to:
| Endpoint | Notes |
|---|---|
GET /api/analysis/{wallet} | Single-network and multi-network analysis (the key covers the entire request, not per network) |
Endpoints that don't consume tokens (status checks, summaries, history) ignore the header.
Choosing a Key
- Pick a value your client can regenerate deterministically across retries — e.g. derive it from your internal request ID or a UUID stored alongside the pending request. A fresh UUID per network attempt defeats the purpose, because retries will produce a different key.
- Keys are opaque strings. Stick to ASCII; 16–128 characters is a comfortable range.
- Each
(user, key)claim is valid for 24 hours. After that, the same key can be reused for a new request.
Semantics
- Same key, identical request: you get the original
jobIdback. No new work, no new charge. - Same key, different parameters: still returns the original
jobId. The server does not re-validate request bodies against the original — the contract is "this key already produced a job, here it is." Treat the key as a pointer to your intent, not as a content hash. - Original job failed: the same key still returns the failed
jobId. To start fresh, use a new key. - Concurrent retries: the claim is atomic, so two simultaneous requests with the same key are guaranteed to map to the same
jobId.
Without the Header
If you don't send Idempotency-Key, every request creates a new job and freezes tokens for it. The header is opt-in, not required.
When to Use It
- Webhook-driven workflows — replays from upstream systems shouldn't multiply charges.
- Client retry loops — wrap a single attempt's
Idempotency-Keyaround the whole retry budget. - Mobile clients — flaky networks make duplicate-submit-on-resume a real risk.
See also: Billing for the underlying freeze / spend / unfreeze flow.