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

# DexUtils API Rate Limits, Quotas, and Retry Handling

> Learn how DexUtils API rate limits work across Free, Standard, and Pro plans, how to read quota headers, and how to handle 429 errors gracefully.

The DexUtils API enforces usage quotas on Free and Standard tier accounts to ensure fair service for all users. If you are on the Pro API plan, you have unlimited access with no daily caps, no per-minute ceilings, and no burst restrictions. Understanding your quota and building retry logic into your integration will keep your application running smoothly regardless of which plan you are on.

## Rate Limit Tiers

Your plan determines how many requests you can make per day, per minute, and in short bursts. The table below summarizes the limits for each tier.

| Plan     | Requests/Day | Requests/Minute | Burst     |
| -------- | ------------ | --------------- | --------- |
| Free     | 10,000       | 60              | 10        |
| Standard | 500,000      | 300             | 50        |
| Pro API  | Unlimited    | Unlimited       | Unlimited |

<Note>
  Pro API customers are not subject to rate limiting and will never receive a `429` response due to quota. Rate limiting applies only to Free and Standard tier accounts.
</Note>

## Rate Limit Response Headers

Every API response includes headers that tell you where you stand against your quota. Inspect these headers proactively to throttle your own requests before you hit the limit.

| Header                  | Description                                                       |
| ----------------------- | ----------------------------------------------------------------- |
| `X-RateLimit-Limit`     | Your total daily request allowance                                |
| `X-RateLimit-Remaining` | How many requests you have left in the current window             |
| `X-RateLimit-Reset`     | Unix timestamp when your quota window resets                      |
| `Retry-After`           | Seconds to wait before retrying (present on `429` responses only) |

## Handling 429 Too Many Requests

When you exceed your quota, the API returns a `429 Too Many Requests` status alongside a `Retry-After` header indicating how many seconds to wait before retrying. The safest approach is exponential backoff so your application recovers gracefully without hammering the API.

<CodeGroup>
  ```python retry.py theme={null}
  import requests
  import time

  API_KEY = "YOUR_API_KEY"
  BASE_URL = "https://api.dexutils.io/v1"

  def fetch_with_retry(path, params=None, max_retries=5):
      headers = {"Authorization": f"Bearer {API_KEY}"}
      url = f"{BASE_URL}{path}"

      for attempt in range(max_retries):
          response = requests.get(url, headers=headers, params=params)

          if response.status_code == 429:
              retry_after = int(response.headers.get("Retry-After", 60))
              wait = retry_after * (2 ** attempt)  # exponential backoff
              print(f"Rate limited. Retrying in {wait}s (attempt {attempt + 1})...")
              time.sleep(wait)
          else:
              response.raise_for_status()
              return response

      raise Exception("Max retries exceeded after repeated 429 responses")
  ```

  ```javascript retry.js theme={null}
  const API_KEY = "YOUR_API_KEY";
  const BASE_URL = "https://api.dexutils.io/v1";

  async function fetchWithRetry(path, params = {}, maxRetries = 5) {
    const headers = { Authorization: `Bearer ${API_KEY}` };
    const query = new URLSearchParams(params).toString();
    const url = `${BASE_URL}${path}${query ? "?" + query : ""}`;

    for (let attempt = 0; attempt < maxRetries; attempt++) {
      const response = await fetch(url, { headers });

      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
        const wait = retryAfter * Math.pow(2, attempt); // exponential backoff
        console.log(`Rate limited. Retrying in ${wait}s (attempt ${attempt + 1})...`);
        await new Promise((resolve) => setTimeout(resolve, wait * 1000));
      } else {
        if (!response.ok) throw new Error(`HTTP ${response.status}`);
        return response;
      }
    }

    throw new Error("Max retries exceeded after repeated 429 responses");
  }
  ```
</CodeGroup>

## Best Practices

Following these habits will help you stay well within your quota limits and keep your integration running smoothly.

<CardGroup cols={2}>
  <Card title="Cache Responses" icon="database">
    Token prices and pool metadata don't change every millisecond. Cache responses locally for at least 10–30 seconds to avoid redundant requests for the same data.
  </Card>

  <Card title="Batch Token Lookups" icon="layer-group">
    Instead of fetching token prices one by one, use `POST /tokens/batch` to retrieve up to 100 token prices in a single request and dramatically reduce your request count.
  </Card>

  <Card title="Monitor Your Headers" icon="chart-bar">
    Read `X-RateLimit-Remaining` on every response. If the value drops below a safe threshold, add a short delay before your next request.
  </Card>

  <Card title="Upgrade to Pro" icon="bolt">
    If your application consistently approaches the Standard tier's per-minute limit, the Pro API plan removes all restrictions and guarantees uninterrupted access.
  </Card>
</CardGroup>

<Tip>
  Use `POST /tokens/batch` whenever you need prices for multiple tokens at once. Batching 100 lookups into one request uses 1% of the quota that 100 individual calls would consume.
</Tip>
