ip_rate_limited. Calls made through the MCP server draw on the same two windows.
A poll every 30 minutes spends 48 requests a day. Sustained production volume needs a license – Index Services.
Those two numbers describe the free tier. GET /v1 reports the limits actually in force for your key as limitMinute and limitDay in its key block, beside remainingMinute and remainingDay, and the rate-limit headers below carry the same figures. Read the key block, not the limits block, whenever the two disagree.
Headers
The sixX-RateLimit-* headers are on every authenticated response, success and error alike. The two pre-authentication rejections, invalid_api_key and ip_rate_limited, have no key to report on and carry none of them. X-Request-Id is on every response, including those two.
Quote
X-Request-Id in any support message. It is what turns “I got a 500 around 14:02” into a single log lookup.
When you are throttled
A rejected request returns429 with Retry-After and an error code that names which limit you hit: rate_limited for the minute window, daily_limit_reached for the day window, ip_rate_limited for the pre-authentication throttle.
Sleep for Retry-After rather than a constant. It is exact on both windows, computed from the moment your oldest counted request ages out, and it agrees to the second with X-RateLimit-Reset and X-RateLimit-Reset-Day.
Error shape
Failures replacedata and meta with a single error object. The code is the stable contract – match on it, not on the message, which is written for a person and may be reworded.
docsUrl deep links to the section for that code on this page. requestId matches the X-Request-Id header.
Error codes
invalid_api_key
The request carried no key, or one that has been revoked, rotated, or never existed. Check the Authorization header, then check the key list in the portal. Keys are personal to an account and are not transferable.
ip_rate_limited
A single address sent too many requests before authenticating. It is an abuse shield in front of key resolution, sized far above the per-key limit, and valid keyed traffic counts toward it. Reaching it means one address is sending a great deal of traffic – most often a loop retrying a rejected key, occasionally many clients behind one address.
rate_limited
The key spent its 60 requests for the current minute. Retry-After is exact here, and X-RateLimit-Reset is the same moment as unix seconds.
daily_limit_reached
The key spent its 2,000 requests for the current day window. Retry-After is exact here, and X-RateLimit-Reset-Day is the same moment as unix seconds. If a workload reaches this regularly, it has outgrown the free tier: Index Services covers sustained and production volume.
not_found
No index or volatility series matches that ticker on this surface. Unknown tickers, unlisted series, and series with no published values yet all return the same 404 – a ticker that is not on the API is not distinguishable from one that does not exist. GET /v1/indices and GET /v1/volatility are the catalogs.
method_not_allowed
The path is a real endpoint, but not with that verb. /v1 is read-only: every endpoint is GET. The response carries an Allow header naming the methods the route accepts.
invalid_parameter
A query parameter failed validation – an unparseable date, a limit outside its range. The message names the parameter.
invalid_interval
interval must be 1h or 1d. See Intervals and the history window below; finer granularity is part of the licensed feed.
invalid_window
start was not before end. The message quotes both values as parsed, to the second, which is usually enough to spot a timezone or ordering mistake in your own input. An end in the future is named as such: history ends at now, so a future end is reported against the current time rather than silently accepted. A window that is merely older than the free range is not this error – it is clamped, not rejected.
internal_error
A fault on our side, not in your request. Retry with backoff. This is the one status where X-Request-Id does the real work: quote it and the failure is a single log lookup rather than a search.
unavailable
The API is temporarily not serving. Retry with backoff. Index levels remain published on beliefsystems.xyz throughout, and the snapshot bundles are static files served independently.
Intervals and the history window
GET /v1/indices/{ticker}/history takes start, end, and interval. interval is 1h or 1d. History reaches back 90 days from now.
All three are optional. With none supplied you get the full trailing window at 1d.
A window that starts earlier is clamped, never rejected. A chart that asked for a year still renders; meta tells you exactly what it got:
A request for
start=2025-12-01&end=2026-06-03&interval=1d, made on August 30, 2026, reaches back past the floor. The window moves; the request does not fail.
points array with clamped: true, rather than an error. Read clamped before labeling a chart with the range you asked for.
Belief Volatility history clamps the same way, against the same 90-day floor, and echoes effectiveStart, clamped, and historyMaxDays.
Full-depth history since inception is in the free snapshot bundles.
Keys
An account holds up to three active keys. The secret is displayed once, at creation, and is never retrievable afterward – the system stores a hash, not the key.- Rotation issues a new secret and retires the old one in the same operation. The old secret stops working immediately; usage history stays with the account.
- Revocation takes effect immediately. Every subsequent call returns
invalid_api_key. - Snapshot file downloads validate keys against a one-minute cache, so a revoked key can still open a snapshot file for up to a minute after revocation. The API itself does not wait.
- Rate limits and history limits are access controls under the Terms of Service. Distributing requests across several keys or accounts to exceed them is prohibited.