Skip to main content
Every Market Data endpoint works without credentials on a free per-IP tier, and with an API key on a much larger per-credential budget. This page covers both, the rate-limit headers you should read, and the conditional-request headers that keep chart-heavy clients cheap.

Free anonymous tier — no signup

Every /v1/* endpoint accepts requests without any credentials. Anonymous requests are rate-limited per source IP, across two independent buckets: That is enough to explore every endpoint, paint charts, and prototype an integration — the try-it panels in these docs run on this tier.
Every response tells you which tier applied:
Never send partial credentials. Sending any of the three API-key headers commits the request to the API-key path. A missing or wrong value then returns 401 instead of falling back to the anonymous tier. This is deliberate — a broken integration fails loudly rather than silently running on the anonymous budget, which is 10× smaller on light and 7.5× smaller on heavy.
The anonymous tier is a courtesy, not a contract. Kairos can switch it off at runtime as an abuse kill switch — applied within ~30s and without a deploy. While it is off, credential-free requests get 401. Build production integrations on an API key.

API keys

For production use, authenticate with the standard Kairos API-key headers — the same credentials used with the REST API:
$CLIENT_ID, $API_KEY, and $API_SECRET are your issued credentials. API keys are issued by the Kairos team during the beta; the key and secret are shown once at issuance. Requests with invalid credentials return 401 — headerless requests ride the anonymous tier instead. A credential presented from a source IP outside its whitelist returns 403 ip_not_whitelisted; that is the only 403 this API emits. If the credential store itself is unreachable, any endpoint can answer 500 with authentication backend unavailable; retry.
A credential’s identity, not its headers, is the rate-limit key. The same key used from several hosts shares one budget. Split traffic across separate credentials if you need separate budgets.

Rate limits

Limits are applied over a one-minute sliding window, in units, across the two independent buckets shown in the table above — per credential when authenticated, per source IP on the anonymous tier. Most requests cost 1 unit. Larger or heavier requests — a wider candle window, a bigger trade-history page, a larger batch of marks — consume more of your budget in proportion to the data returned; a typical chart paint or lookup still costs only a handful of units. Each operation’s exact cost model is published as x-kairos-rate-limit in the OpenAPI spec:

Reading the headers

Every response reports the bucket it drew from and what remains:
X-RateLimit-Reset is the unix second at which the current one-minute window rolls over — that is when budget meaningfully replenishes. Exceeding a budget returns 429 with a Retry-After header (seconds until that rollover). The two buckets are independent: exhausting the heavy budget never blocks candle or metadata requests.
There are two different 429s. A coarser per-IP admission gate sits in front of authentication. It also answers 429 rate_limited, but with the message too many requests from this address, a flat Retry-After: 60, and no X-RateLimit-* headers — that absence is how you tell the two apart. It exists to keep floods off shared infrastructure and sits far above any legitimate traffic rate.
The limiter fails closed. If its backing store is unreachable, requests get 503 rate_limiter_unavailable rather than passing unmetered. Retry with backoff.
Contact the team if your integration needs higher budgets — limits are set per credential and can be raised.

Conditional requests

Cacheable responses carry a strong ETag. Repeat requests that include If-None-Match return 304 Not Modified with no body, and cost you nothing in bandwidth:
The If-None-Match value is the ETag from your previous response, quotes included. Cache-Control on each response indicates how long it may be reused — fully historical data is cacheable for much longer than recent or live data. Respecting these headers is the easiest way to cut bandwidth and latency for chart-heavy clients.

Errors