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

# Rate Limits & Errors

> Rate limits, error codes, and how to handle them.

## Rate limits

Rate limits are enforced per API key.

| Tier | Requests / minute |
| - | - |
| Free | 10 |
| Explorer | 100 |
| Builder | 1,000 |
| Enterprise | 10,000 |

When you exceed the rate limit, the API returns `429 Too Many Requests` with a `Retry-After` header indicating how many seconds to wait.

## Per-request query window

Every query endpoint (`/v1/fills`, `/v1/trades`, `/v1/candles`, `/v1/funding`, `/v1/open-interest`, `/v1/mark-prices`, `/v1/vault-operations`, and all `/v1/analytics/*`) enforces a maximum `to - from` window per request. This is independent of the archive-depth cap — you can reach any historical date within your tier, but each call must cover a bounded range.

| Tier | Max window per request (with market/address filter) | Max window (no filter) |
| - | - | - |
| Free | 1h | 1h |
| Explorer | 24h | 4h |
| Builder | 7d | 4h |
| Enterprise | unlimited | 4h |

Exceeding the window returns `400 QUERY_WINDOW_EXCEEDED`. Paginate by shifting `from` and `to` forward, not by raising `limit`. The no-filter 4h cap exists because unfiltered queries against billions of rows blow past database resource limits.

## Handling rate limits

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Ironflow, RateLimitError } from "@ironflowsh/sdk";

  const client = new Ironflow("if_your_api_key");

  try {
    const trades = await client.trades("BTC-PERP");
  } catch (err) {
    if (err instanceof RateLimitError) {
      console.log(`Rate limited. Retry in ${err.retryAfterMs}ms`);
      await new Promise(r => setTimeout(r, err.retryAfterMs));
      // retry...
    }
  }
  ```

  ```python Python theme={null}
  import asyncio
  from ironflow_sdk import Ironflow
  from ironflow_sdk.errors import RateLimitError

  async with Ironflow("if_your_api_key") as client:
      try:
          trades = await client.trades("BTC-PERP")
      except RateLimitError as e:
          print(f"Rate limited. Retry in {e.retry_after_ms}ms")
          await asyncio.sleep(e.retry_after_ms / 1000)
          # retry...
  ```
</CodeGroup>

## Error codes

All errors follow the same shape:

```json theme={null}
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 60 seconds."
  }
}
```

| HTTP Status | Code | Meaning |
| - | - | - |
| `400` | `INVALID_PARAMETER` | Missing or invalid parameters (e.g. `address` required but not provided) |
| `400` | `INVALID_MARKET_CLASS` | Perp-only endpoint called with a spot or prediction symbol |
| `400` | `QUERY_WINDOW_EXCEEDED` | `to - from` exceeds the per-request window for your tier — narrow the window and paginate |
| `400` | `QUERY_TOO_EXPENSIVE` | Server refused because the query would scan too many rows or bytes — add a market filter, narrow the window, or lower the limit |
| `401` | `UNAUTHORIZED` | Missing or invalid API key |
| `403` | `TIER_FORBIDDEN` | Your tier does not include this feature |
| `429` | `RATE_LIMIT_EXCEEDED` | Too many requests — check `Retry-After` header |
| `500` | `INTERNAL_ERROR` | Unexpected server error |
| `504` | `QUERY_TIMEOUT` | Query exceeded the 15-second execution budget — narrow the window, add a filter, or lower the limit |

## SDK error classes

Both SDKs provide typed error classes:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import {
    IronflowError,   // base class
    AuthError,       // 401
    TierError,       // 403
    RateLimitError,  // 429 — has .retryAfterMs
  } from "@ironflowsh/sdk";
  ```

  ```python Python theme={null}
  from ironflow_sdk.errors import (
      IronflowError,   # base class
      AuthError,       # 401
      TierError,       # 403
      RateLimitError,  # 429 — has .retry_after_ms
  )
  ```
</CodeGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.