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

# Rate Limits

> API rate limiting by plan, response headers, and retry strategies

The DevHelm API enforces rate limits per organization using a sliding-window algorithm. Limits vary by plan and are shared across all API keys in the same organization.

## Limits by plan

| Plan       | Requests per minute |
| ---------- | ------------------- |
| Free       | 100                 |
| Starter    | 1,000               |
| Pro        | 5,000               |
| Team       | 5,000               |
| Business   | 100,000             |
| Enterprise | 100,000             |

## Response headers

Every authenticated API response includes rate limit headers:

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the window          |
| `X-RateLimit-Remaining` | Requests remaining in the current window        |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the window resets |

```
HTTP/1.1 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 1712956860
```

## When rate limited

When you exceed the limit, the API returns `429 Too Many Requests` with a `Retry-After` header and the standard error envelope:

```
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1712956860
```

```json theme={null}
{
  "status": 429,
  "code": "RATE_LIMITED",
  "message": "Rate limit exceeded. Try again at 1712956860.",
  "timestamp": 1712956848000,
  "requestId": "a1b2c3d4-5678-90ab-cdef-111111111111"
}
```

The `Retry-After` header value is in seconds. The `message` field references the reset timestamp for human readability.

## Retry strategy

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      const response = await fetch(url, options);

      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get("Retry-After") || "5");
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        continue;
      }

      return response;
    }
    throw new Error("Max retries exceeded");
  }
  ```

  ```python Python theme={null}
  import time
  import requests

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

          if response.status_code == 429:
              retry_after = int(response.headers.get("Retry-After", "5"))
              time.sleep(retry_after)
              continue

          return response
      raise Exception("Max retries exceeded")
  ```
</CodeGroup>

## Best practices

<AccordionGroup>
  <Accordion title="Monitor remaining quota">
    Check the `X-RateLimit-Remaining` header in responses and throttle proactively when it gets low, rather than waiting for 429 errors.
  </Accordion>

  <Accordion title="Use webhooks for events">
    Instead of polling for status changes, use [platform webhooks](/integrations/webhooks) to receive real-time event notifications.
  </Accordion>

  <Accordion title="Cache read-heavy data">
    For data that doesn't change frequently (service catalog, monitor configurations), cache responses locally and refresh periodically.
  </Accordion>

  <Accordion title="Batch operations with Config as Code">
    Instead of creating monitors one at a time via API calls, define them in `devhelm.yml` and deploy in a single operation.
  </Accordion>
</AccordionGroup>

## Unauthenticated rate limits

Public endpoints (service catalog, status data) have a separate IP-based rate limit of **60 requests per minute** per IP address. This limit is independent of the organization-level limit.

## Check your current limits

```bash API theme={null}
curl https://api.devhelm.io/api/v1/auth/me \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"
```

The response includes rate limit info for your API key:

```json theme={null}
{
  "rateLimits": {
    "requestsPerMinute": 5000,
    "remaining": 4950,
    "windowMs": 60000
  }
}
```
