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

# Rate limits

> Understand the rate limits applied to Bayse Markets API endpoints

## Overview

Rate limits protect the API from abuse and ensure fair usage for all users. When you exceed a rate limit, the API returns a `429 Too Many Requests` response with a `Retry-After` header and a `retryAfter` field indicating how many seconds to wait before retrying.

## API key rate limits

Authenticated endpoints are rate-limited **per API key** based on whether the endpoint is a read or write operation.

| Type            | Limit              | Scope       |
| --------------- | ------------------ | ----------- |
| Read endpoints  | 30 requests/second | Per API key |
| Write endpoints | 20 requests/second | Per API key |

Read endpoints are those that require `X-Public-Key` only. Write endpoints are those that require `X-Public-Key`, `X-Timestamp`, and `X-Signature`. See the [Authentication guide](/authentication) for details.

When the limit is exceeded:

```json theme={null}
{
  "message": "Rate limit exceeded. Please try again later.",
  "retryAfter": 1
}
```

The response also includes a `Retry-After` header with the number of seconds to wait.

## API key management

API key management endpoints are rate-limited **per session token** to prevent abuse. Each user can have a maximum of **2 active API keys** at any time.

| Operation      | Limit      | Window     | Scope       |
| -------------- | ---------- | ---------- | ----------- |
| Create API key | 2 requests | 30 minutes | Per session |
| Revoke API key | 2 requests | 30 minutes | Per session |
| Rotate API key | 2 requests | 30 minutes | Per session |

Rotation shares the revoke limit since it revokes the existing key and creates a new one.

When the limit is exceeded:

```json theme={null}
{
  "message": "Rate limit exceeded. Please try again later.",
  "retryAfter": 900
}
```

The `retryAfter` value reflects the actual time remaining until the next request is allowed.

## Login endpoint

The login endpoint (`POST /v1/user/login`) is rate-limited to **1 request per 2 minutes** per email address.

| Endpoint              | Limit     | Window    | Scope             |
| --------------------- | --------- | --------- | ----------------- |
| `POST /v1/user/login` | 1 request | 2 minutes | Per email address |

When the limit is exceeded:

```json theme={null}
{
  "message": "Too many login attempts. Please try again later.",
  "retryAfter": 120
}
```

## Handling rate limit errors

```javascript Node.js theme={null}
async function fetchWithRetry(url, options) {
  const response = await fetch(url, options);

  if (response.status === 429) {
    const { retryAfter } = await response.json();
    console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    return fetchWithRetry(url, options);
  }

  return response.json();
}
```

### Best practices

* **Handle 429 gracefully** — if you receive a rate limit response, wait for the `retryAfter` duration before retrying.
* **Cache your session token** — after a successful login, store the returned `token` and `deviceId` and reuse them for subsequent API key operations. There's no need to log in again for each request.
* **Don't poll the login endpoint** — the login endpoint is intended for one-time session creation, not repeated calls.
* **Batch where possible** — if you need data for multiple markets, use list endpoints instead of making individual requests.
