> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gains.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and limits

> One envelope, stable machine-readable codes, proper HTTP statuses, and the rate limits.

## Envelope

Every error is JSON with a stable `code`, a human `message` and, when useful, `details` with the numbers the message quotes:

```json theme={null}
{
  "code": "PRECISION_ERROR",
  "message": "size exceeds 5 decimals",
  "details": { "field": "size", "value": "0.123456", "maxDecimals": 5 }
}
```

Match on `code`, never on `message`. The SDK surfaces the same fields on `GainsApiError`.

## Codes

| HTTP | Code                                                                                                 | When                                                                                                                                                                                                                    |
| ---- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `VALIDATION_ERROR`                                                                                   | The body or query does not match the schema; `details.issues` lists each path.                                                                                                                                          |
| 401  | `UNAUTHENTICATED`                                                                                    | Missing signature headers or API key on a private endpoint.                                                                                                                                                             |
| 401  | `INVALID_SIGNATURE`                                                                                  | The signature does not recover to `X-Gains-Agent`.                                                                                                                                                                      |
| 401  | `TIMESTAMP_OUT_OF_WINDOW`                                                                            | `X-Gains-Timestamp` is more than 30 s from server time.                                                                                                                                                                 |
| 401  | `NONCE_REUSED`                                                                                       | `X-Gains-Nonce` was already used by this agent.                                                                                                                                                                         |
| 401  | `AGENT_UNKNOWN`, `API_KEY_UNKNOWN`                                                                   | Not registered on this chain.                                                                                                                                                                                           |
| 403  | `AGENT_NOT_DELEGATED`                                                                                | The trader's on-chain delegate is not this agent; `details.delegationTx` carries the `setTradingDelegate(agent)` transaction (for facade agents, the relayer).                                                          |
| 403  | `AGENT_EXPIRED`, `AGENT_REVOKED`                                                                     | Scope expiry passed, or revoked.                                                                                                                                                                                        |
| 403  | `SCOPE_READ_ONLY`, `SCOPE_MARKET_NOT_ALLOWED`, `SCOPE_LEVERAGE_EXCEEDED`, `SCOPE_SPEND_CAP_EXCEEDED` | The agent's scope forbids the action.                                                                                                                                                                                   |
| 403  | `TRADER_MISMATCH`                                                                                    | The address in the path is not the account the credentials belong to.                                                                                                                                                   |
| 404  | `CHAIN_NOT_FOUND`, `MARKET_NOT_FOUND`, `ORDER_NOT_FOUND`, `POSITION_NOT_FOUND`, `AGENT_NOT_FOUND`    |                                                                                                                                                                                                                         |
| 409  | `IDEMPOTENCY_CONFLICT`                                                                               | `clientId` already used with a different order.                                                                                                                                                                         |
| 409  | `ORDER_NOT_MODIFIABLE`                                                                               | The order is not in a state that accepts the change (for example a pending market request before the oracle timeout).                                                                                                   |
| 422  | `PRECISION_ERROR`                                                                                    | More decimals than the market allows.                                                                                                                                                                                   |
| 422  | `LEVERAGE_OUT_OF_RANGE`, `SIZE_BELOW_MINIMUM`, `MARKET_CLOSED`, `COLLATERAL_NOT_SUPPORTED`           | Domain rules.                                                                                                                                                                                                           |
| 422  | `SIMULATION_REVERTED`                                                                                | The contracts would revert for this transaction; `details.errorName` is the custom error (for example `InsufficientCollateral`, `WrongLeverage`) and `details.calldata` the inner call to replay. Nothing was prepared. |
| 422  | `SUBMISSION_MISMATCH`                                                                                | The hash reported to `POST /orders/{id}/submit` mined without creating an order for this trader.                                                                                                                        |
| 422  | `UNSUPPORTED`                                                                                        | Not available on this deployment or in v1 (for example writes on a read-only deployment).                                                                                                                               |
| 429  | `RATE_LIMITED`                                                                                       | Slow down; retry after the window.                                                                                                                                                                                      |
| 502  | `UPSTREAM_UNAVAILABLE`                                                                               | A Gains backend behind the API did not answer. Retry.                                                                                                                                                                   |
| 503  | `NOT_READY`                                                                                          | The API is starting or a data feed is stale. Retry.                                                                                                                                                                     |
| 503  | `CHAIN_READ_ONLY`                                                                                    | This deployment has no relayer for the Hyperliquid facade on the chain; native reads and writes are unaffected.                                                                                                         |
| 500  | `INTERNAL`                                                                                           | A bug. Report it with the `cf-ray` response header and the time of the call.                                                                                                                                            |

Rejections that happen **after** a transaction is sent are not HTTP errors: the order is created and moves to `rejected` with a `reason`, see [Orders](/developer/trading-api/orders#rejections).

## Retry guidance

| Safe to retry as-is                                                          | Fix first                                                                  | Never retry blindly                                                                                                             |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `RATE_LIMITED`, `NOT_READY`, `UPSTREAM_UNAVAILABLE`, network errors on `GET` | `VALIDATION_ERROR`, `PRECISION_ERROR`, scope errors, `AGENT_NOT_DELEGATED` | A `POST /orders` that timed out on the network: read `GET /account/{address}/orders` or use `clientId` so a retry is idempotent |

## Rate limits

| Scope                                         | Limit                                  |
| --------------------------------------------- | -------------------------------------- |
| Per IP                                        | 600 requests per minute, all endpoints |
| Per agent or API key                          | 300 requests per minute                |
| Per agent, writes (`POST`, `PATCH`, `DELETE`) | 60 per minute                          |
| Per WebSocket connection                      | 200 subscriptions                      |

Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` (seconds) for the tightest bucket that applied. Exceeding one answers `429 RATE_LIMITED` with `Retry-After` and `details.scope` (`ip`, `agent` or `agent-writes`). Windows are fixed one-minute windows.

These are the launch values on testnet; production limits are published with the mainnet release.
