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

# Access and Rate Limits

> The Polaris access model across REST, SDKs, CLI, and MCP: API keys, public windows per endpoint, rate limits, pagination, and error handling.

One access model applies to the REST API, the SDKs, the CLI, and the hosted MCP server. This page defines it once; endpoint pages list only their exceptions.

Every curl example in these docs runs without an API key on the current public window.

## Authentication

| Method | Use |
| - | - |
| No key (anonymous) | Public windows below, on open sources |
| `POLARIS_API_KEY` environment variable | SDKs and CLI read this automatically |
| Bearer header / `api_key` constructor argument | REST `Authorization: Bearer $POLARIS_API_KEY`; SDK client argument |

Manage keys and plans at [polaris.supply/keys](https://www.polaris.supply/keys). Live keys have the form `pk_live_...`; treat them as secrets and never embed them in source code.

The hosted MCP server at `https://mcp.polaris.supply` offers the same queries with anonymous public access, optional API-key authentication, or per-call x402 payment for restricted tools — see [MCP server setup](https://polaris.supply/mcp-server).

## Public windows per endpoint

For anonymous requests, most standardized routes expose a rolling latest-hour window; preview sources clamp their public range around `public_cutoff_date`. A Polaris API key unlocks older history.

| Endpoint | Anonymous (no key) | With a key |
| - | - | - |
| [Trades](/endpoints/trades), [L2 Deltas](/endpoints/l2-updates), [L2 orderbooks](/endpoints/l2-orderbooks), [Funding rates](/endpoints/funding-rates), [Perpetual ticker](/endpoints/perpetual-ticker), [Options ticker](/endpoints/options-ticker), [OHLCV](/endpoints/ohlcv) | Rolling latest hour | Full covered history |
| [Intents](/endpoints/intents), [Quotes](/endpoints/quotes) | Rolling latest hour | Full covered history |
| [Events](/endpoints/events) | Not available — key and both time bounds required | Bounded mixed-event queries |
| [Raw data](/endpoints/raw) | Latest seven days; `start` and `end` required | Full capture history |
| [Catalog](/endpoints/catalog), [Instruments](/endpoints/catalog-instruments), [Counts](/endpoints/count) | Fully public | Fully public |

Bounds behavior shared by the latest-hour routes:

* No bounds: the query covers the latest hour.
* Only `start` (inside the rolling hour): queries through now.
* Only `end` (inside the rolling hour): covers the preceding hour, clamped to the cutoff.
* Explicit bounds entirely inside the rolling hour are public; older rows require a key.
* During anonymous pagination, rows that age out of the public hour are skipped.

Preview sources expose only the bounded range around `public_cutoff_date` — the UTC day it names. Read each Catalog row's `start`, `end`, and `access` before choosing a time range.

## Rate limits

Anonymous reads are capped at 1 GiB per request and two concurrent queries per API replica. Requests that exceed a limit or burst rate return `429` with a `Retry-After` header; honor it before retrying.

Reconstruction work has its own caps: [L2 orderbooks](/endpoints/l2-orderbooks) replays at most 100,000 matching raw captures, 1 GiB of reads, and 30 seconds per request, and returns `422` when a query exceeds them. Narrow the range or use [L2 Deltas](/endpoints/l2-updates) for larger scans.

## Pagination

All list endpoints use opaque keyset cursors:

1. Pass `next_cursor` as `cursor` on the next request, with the same filters.
2. Stop when `has_more` is false or `next_cursor` is null.
3. Never edit a cursor or reuse it with different filters; some cursors are bound to the complete query, so repeat every filter (`start`, `end`, `types`, `source`, `market`, `instrument`, and endpoint-specific IDs such as `intent_id`).

## Errors

Error responses share one envelope:

```json theme={null}
{
  "error": {
    "code": "...",
    "message": "...",
    "resolution": "..."
  }
}
```

`error.resolution` states the corrective action; surface it to the user rather than guessing.

| Status | Meaning | Recovery |
| - | - | - |
| `400` | Malformed request | Check parameter names, types, and formats |
| `401` | Missing or invalid API key | Set `POLARIS_API_KEY` or pass a valid key |
| `404` | Unknown source, channel, or route | Resolve identifiers from [Catalog](/endpoints/catalog) |
| `422` | Query refused as too expensive or unbounded | Narrow `start`/`end` or reduce `limit` |
| `429` | Rate limit exceeded | Wait for `Retry-After`, then retry |
| `503` | Service temporarily unavailable | Retry with backoff |

The SDKs raise typed errors for the common cases (`UnauthorizedError`, `RateLimitedError`, and related classes); see the error-handling sections of the [Python](/sdks/python#error-handling) and [TypeScript](/sdks/typescript#error-handling) SDK pages. Rust surfaces the same cases as `Result` error variants; see the [Rust SDK](/sdks/rust).

The authoritative machine-readable contract is the [OpenAPI document](https://api.polaris.supply/openapi.json).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.