Documentation Index
Fetch the complete documentation index at: https://docs.nxos.io/llms.txt
Use this file to discover all available pages before exploring further.
Idempotency
A request might time out before you read the response. You don’t know if it ran. Replaying it could create a duplicate payout, beneficiary, or quote. TheIdempotency-Key header solves this. Pass a unique value on every write request. We cache the response for 24 hours keyed by (organization, key, method, path). A retry within that window returns the cached response. The handler does not run twice.
How to use it
Generate a unique key per operation (UUID v4 is fine) and send it on any non-GET request:Outcomes
| Scenario | Outcome |
|---|---|
| First request with a fresh key | Handler runs. Response is cached and returned. |
| Retry, same key, same body, response cached | Cached response is returned. The Idempotent-Replayed: true header is set so you can detect the cache hit. |
| Retry, same key, same body, original still in flight | 409 idempotency_request_in_flight. Wait briefly and retry. |
| Retry, same key, different body | 409 idempotency_key_in_use. You reused the key for a different operation. Generate a new key. |
Original returned 5xx | Not cached. The next attempt re-acquires the key and runs the handler. |
Caching policy
We cache2xx and 4xx responses. Same key + same body always returns the same response.
We do not cache 5xx. Server errors are usually transient. Your retry should hit a healthy server, not a stale cached failure.
Key requirements
- Maximum 255 characters
- Unique per logical operation (UUID v4 recommended)
- Reuse the same key for retries of the same operation. Do not reuse it for a different operation.
Scope
Keys are scoped per organization, per HTTP method, per request path. The same key value is independent acrossPOST /v1/quotes and POST /v1/transactions/crypto-payouts. They are different operations.
GET endpoints ignore the header.
Rate limits
Every API endpoint is rate-limited per organization. The default cap is 1,000 requests per minute, applied as a tumbling 60-second window.Per organization, not per key
Limits apply to your organization. Creating more API keys does not raise your quota. Your throughput is one number across all your keys.Response headers
Every successful response (and every429) includes these headers so you can pace yourself before hitting the limit:
| Header | Value |
|---|---|
X-RateLimit-Limit | The cap configured for your organization. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets. |
When you exceed the limit
Requests beyond the cap return429 rate_limited with a Retry-After header indicating seconds until the window resets:
Retry-After rather than retrying right away.
Handling 429 in your client
IP-based protection
A separate edge rule (CloudFront WAF) caps requests per source IP for abuse and DDoS protection. That layer is independent of the per-organization quota above. Most partners never see it. If you do, contact support.How they interact
A429 response is not cached. Your next attempt with the same Idempotency-Key re-runs against the rate-limited handler. Once the window resets, the request is admitted normally.
A cached replay (Idempotent-Replayed: true) does count against your rate limit. The cached response is still a request you sent us. If you see high replay volume, your client is sending the same request more often than it needs to. Check the client logic.
Send an
Idempotency-Key on every write request. Honor Retry-After on 429. That covers the two most common ways an integration breaks.