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

# Rate limits

> Understand API rate limits, response headers, and retry strategies.

# Rate limits

Kynasmith applies rate limits to protect service stability and ensure fair access across all customers. Rate limits are separate from [billing quotas](/billing/overview) — exceeding a rate limit is a temporary throttle, not a billing event.

## Default limits

Rate limits are applied per project and per organization. The following are the default limits; your plan may include higher limits.

| Scope               | Limit                          | Window                   |
| ------------------- | ------------------------------ | ------------------------ |
| Per project         | 100 requests/minute            | Rolling 60-second window |
| Per organization    | 500 requests/minute            | Rolling 60-second window |
| Session creation    | 10 sessions/minute per project | Rolling 60-second window |
| MoveSpec operations | 60 requests/minute per project | Rolling 60-second window |

<Note>
  These are placeholder default values. Actual limits may differ based on your plan. Contact support if you need higher limits for your use case.
</Note>

## Affected endpoints

Rate limits apply to all API endpoints. Active session connections are not subject to HTTP rate limits, but session creation is rate-limited as shown above.

## Rate limit headers

Every API response includes rate limit headers so you can monitor your usage proactively:

| Header                | Description                                                   |
| --------------------- | ------------------------------------------------------------- |
| `RateLimit-Limit`     | The maximum number of requests allowed in the current window. |
| `RateLimit-Remaining` | The number of requests remaining in the current window.       |
| `RateLimit-Reset`     | The time (in seconds) until the current window resets.        |

When a request is throttled, the response also includes:

| Header        | Description                                    |
| ------------- | ---------------------------------------------- |
| `Retry-After` | The number of seconds to wait before retrying. |

## 429 response shape

When rate limited, the API returns HTTP 429 with the standard error envelope:

```json theme={null}
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after 2 seconds.",
    "retryable": true,
    "details": {
      "retry_after_seconds": 2
    }
  }
}
```

## Recommended retry strategy

When you receive a 429 response:

1. **Read the `Retry-After` header** to determine how long to wait.
2. **Use exponential backoff with jitter** if no `Retry-After` is present:
   * Base delay: 1 second
   * Multiplier: 2x per retry
   * Jitter: random 0-500ms added to each delay
   * Maximum retries: 3-5 depending on your use case
3. **Do not retry in a tight loop.** Repeated 429s without backoff may result in longer throttle periods.

### Python example

```python theme={null}
import time
import random

def retry_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except RateLimitError as e:
            if attempt == max_retries - 1:
                raise
            delay = min(2 ** attempt + random.uniform(0, 0.5), 30)
            if e.retry_after:
                delay = e.retry_after
            time.sleep(delay)
```

### JavaScript example

```ts theme={null}
async function retryWithBackoff<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      if (error.code !== "rate_limited") throw error;

      const delay = Math.min(2 ** attempt + Math.random() * 0.5, 30);
      const retryAfter = error.retryAfter ?? delay;
      await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
    }
  }
  throw new Error("Unreachable");
}
```

## Rate limiting vs. billing quotas

| Concern           | Error code              | HTTP status | Meaning                                                                               |
| ----------------- | ----------------------- | ----------- | ------------------------------------------------------------------------------------- |
| Rate limiting     | `rate_limited`          | 429         | Temporary throttle for abuse protection. Retry after the indicated duration.          |
| Billing quota     | `quota_exceeded`        | 403         | Plan-based usage limit reached. Upgrade your plan or wait for the quota reset period. |
| Plan feature gate | `plan_requires_upgrade` | 403         | Feature not available on your current plan. Upgrade required.                         |

Rate limits reset automatically within the rolling window. Billing quotas reset on your billing cycle (typically monthly). See [Billing](/billing/overview) for details on quota management.
