# Rate Limiting

To keep the platform fast and fair, the API limits how many requests each
account can make in a short window. If you exceed the limit, further requests are
temporarily rejected with **HTTP 429 (Too Many Requests)** until the window
resets. Rate limits protect you too — they stop a runaway script from exhausting
your account's capacity.

## How the limits work

- **Per account.** Limits apply to your Sheetgo **user account**, across *all* of
  your API keys combined. Creating extra API keys does **not** add capacity — the
  budget is shared by the account.
- **Two separate budgets:**
  - **Reads** — `GET` and `HEAD` requests (higher allowance).
  - **Writes** — `POST`, `PUT`, `PATCH`, `DELETE` requests (lower allowance).
- **Per-minute window.** Each budget refills on a rolling one-minute basis.

Current default limits (per account, per minute): **120** read, **30** write.
Do **not** hard-code these numbers — some accounts have higher allowances and
limits may change. Read the limit from the response headers instead.

## Response headers (on every response)

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` | Your current limit for that category (read or write). |
| `X-RateLimit-Remaining` | Requests left in the current window. |
| `X-RateLimit-Reset` | Seconds until the window resets. |

When `X-RateLimit-Remaining` approaches `0`, slow down **before** you get
blocked — the most effective way to avoid 429s.

## When you are throttled

A `429` response includes a `Retry-After` header and a JSON body:

```json
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded: 120 read requests per minute. Retry after 37 seconds.",
  "retry_after": 37,
  "limit": 120,
  "remaining": 0,
  "reset": 37,
  "scope": "read"
}
```

| Field | Meaning |
|---|---|
| `error` | Stable code: always `rate_limit_exceeded`. |
| `message` | Human-readable explanation. |
| `retry_after` | Seconds to wait before retrying (same as the `Retry-After` header). |
| `limit` / `remaining` / `reset` | Your limit, requests left (`0`), seconds to reset. |
| `scope` | Which budget you exhausted: `read` or `write`. |

## Consuming the API reliably

1. **Honor `Retry-After` on a 429** — wait at least that many seconds before retrying.
2. **Use exponential backoff with jitter** for other transient errors.
3. **Self-throttle** using `X-RateLimit-Remaining` — slow down proactively.
4. **Spread work out** with small delays rather than bursting.
5. **Cache and avoid redundant calls** — reads count even when data is unchanged.
6. **Treat 429 as normal** — catch it, wait, and retry transparently.

Reference retry loop:

```python
for attempt in range(max_retries):
    resp = call_api(...)
    if resp.status_code != 429:
        return resp
    wait = int(resp.headers.get("Retry-After", 2 ** attempt))
    sleep(wait + random_jitter())
```

## Automated agents and LLM tools

The response **body** carries everything needed to recover (`retry_after`,
`scope`, and a plain-language `message`) — parse the body, not just the status
code. Honor `retry_after` rather than retrying in a tight loop. Most HTTP client
libraries already back off automatically on `429` + `Retry-After`; keep that on.

## Need higher limits?

If your legitimate workload consistently approaches the limits, contact **Sheetgo
support** to raise your account's capacity. A change takes effect automatically —
and because you read the limit from `X-RateLimit-Limit`, your integration needs no
code change.


---

More: start page https://dev-api.sheetgo.com/rest/reference.md, everything in one file https://dev-api.sheetgo.com/rest/llms-full.txt, OpenAPI https://dev-api.sheetgo.com/rest/openapi.json.
