# Errors and limits

Use idempotency keys, bounded retries, and trade polling to keep integrations predictable.

## Idempotency

Wallet and financial mutations require `Idempotency-Key`. Reusing a key with the same request recovers the original operation. Store the exact body and key before sending the request. For a batch, preserve the entry order as well.

Use a new key for a new operation only after resolving any earlier submission. A timeout, disconnect, expired quote, or later rate-limit response does not prove that the original trade failed. Once a trade ID is known, poll its status instead of starting another trade.

Some settings changes, such as tracker settings and referral-code selection, do not use an idempotency header. The portfolio batch POST is a read. Check the endpoint's request schema instead of treating every POST as a financial mutation.

## Rate limits

| Scope | Limit |
| --- | --- |
| Account API traffic | 100 requests per second with a burst of 200 |
| Single trade submission, shared by quote submission and one-request execution | 5 requests per second with a burst of 5 |
| Trade batch submission | 1 request per second |
| Coordinated clip submission | 1 request per second |
| Buy-route previews | 10 requests per second with a burst of 10 |
| Wallet export, shared by single and bulk export | 5 requests per minute with a burst of 5 |
| Wallet import | 5 requests per minute with a burst of 5 |
| Withdrawals | 10 requests per minute with a burst of 10 |
| Account-to-account transfers | 10 requests per minute with a burst of 10 |

Limits are account-scoped. Endpoint limits apply in addition to the account limit; market-data and automation endpoints have their own limits too. Provider capacity and the website proxy may impose further limits. Use bounded backoff with jitter and avoid retrying every request at once.

## Retry decisions

| Status | Action |
| --- | --- |
| `400` | Correct the request before retrying |
| `401` | Replace or reauthorize the API key |
| `403` | Check credential scope, browser-session requirements, and CSRF headers |
| `404` | Confirm the wallet, quote, trade, or ticket identifier |
| `409` | Resolve the conflicting resource state |
| `429` | Retry with bounded exponential backoff |
| `503` | Retry temporary failures with bounded exponential backoff |

Keep the same idempotency key when retrying a mutation after a timeout, `429`, or temporary `503`.

HTTP `202` means a trade was accepted for asynchronous execution. It does not mean the trade confirmed. Follow `queued`, `submitted`, and `awaiting_ticket_refund` until `confirmed` or `failed`. A balance or portfolio refresh can fail after a successful trade; retry the read without submitting another trade.
