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.
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 returns401instead 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 onlightand 7.5× smaller onheavy.
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 asx-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 different429s. A coarser per-IP admission gate sits in front of authentication. It also answers429 rate_limited, but with the messagetoo many requests from this address, a flatRetry-After: 60, and noX-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 strongETag. Repeat requests that include
If-None-Match return 304 Not Modified with no body, and cost you nothing in
bandwidth:
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.

