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

# Rate Limiting

> API rate limits, response headers, and how to handle exceeded limits.

# Rate Limiting

The Tedro API enforces rate limits to protect the platform and ensure fair usage. Limits are applied per IP address and persist across server restarts.

## Rate Limit Tiers

The API has three tiers of rate limiting, applied from most restrictive to least:

### Sensitive Endpoints

High-security endpoints that handle password resets and credential operations:

| Endpoint                         | Limit      | Window |
| -------------------------------- | ---------- | ------ |
| `POST /api/auth/forget-password` | 3 requests | 1 hour |
| `POST /api/auth/reset-password`  | 3 requests | 1 hour |

### Authentication Endpoints

All endpoints under `/api/auth/*`:

| Endpoint                       | Limit       | Window     |
| ------------------------------ | ----------- | ---------- |
| `POST /api/auth/sign-in/email` | 5 requests  | 60 seconds |
| `POST /api/auth/sign-up/email` | 3 requests  | 5 minutes  |
| All other `/api/auth/*`        | 10 requests | 60 seconds |

<Note>
  Sign-in has additional brute force protection: 5 failed attempts per email+IP triggers a 15-minute lockout, independent of the rate limit counter. See [Authentication](/api-reference/authentication) for details.
</Note>

### General API

All endpoints under `/api/*` (applied after auth-specific limits):

| Scope                  | Limit        | Window     |
| ---------------------- | ------------ | ---------- |
| All `/api/*` endpoints | 100 requests | 60 seconds |

## Response Headers

When rate limits are active, responses include standard rate limit headers ([draft-7](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/)):

| Header                | Description                              | Example |
| --------------------- | ---------------------------------------- | ------- |
| `RateLimit-Limit`     | Maximum requests allowed in the window   | `100`   |
| `RateLimit-Remaining` | Requests remaining in the current window | `87`    |
| `RateLimit-Reset`     | Seconds until the window resets          | `42`    |

## When You Exceed a Limit

If you exceed a rate limit, the API returns a `429 Too Many Requests` response:

```json theme={null}
{
  "error": "Too many requests, please try again later"
}
```

The response includes a `Retry-After` header indicating how many seconds to wait before retrying:

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

{"error": "Too many requests, please try again later"}
```

## Best Practices

1. **Respect `Retry-After`** -- When you receive a 429, wait the specified number of seconds before retrying
2. **Implement exponential backoff** -- For automated scripts, use exponential backoff with jitter to avoid thundering herd effects
3. **Cache responses** -- Reduce API calls by caching GET responses on your end
4. **Use pagination efficiently** -- Fetch only the data you need with appropriate `limit` values
5. **Monitor headers** -- Track `RateLimit-Remaining` to proactively slow down before hitting limits

## Example: Handling Rate Limits in Node.js

```javascript theme={null}
async function fetchWithRateLimit(url, options) {
  const response = await fetch(url, options);

  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);
    console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    return fetchWithRateLimit(url, options); // Retry
  }

  return response;
}
```
