Reference

Errors & rate limits

One error envelope across every endpoint. Per-minute rate limits scaled by plan (100/min on Reads, 300/min on Reads + Webhooks) — surfaced via standard headers on every response.

Error envelope

The same shape on every endpoint, on every status code from 400 upward.

{
  "error": {
    "code": "invalid_query",
    "message": "Unknown field 'percent_change'. Did you mean 'day_change_pct'?",
    "request_id": "req_01J9PZA1F2C9V3XQ"
  }
}

Always include the request_id when you contact support. It points us at the exact log entry for your request.

Error codes

Stable, machine-readable codes. The HTTP status is set accordingly.

CodeStatusWhen you see it
invalid_request400The request was malformed (bad JSON, missing required parameter, invalid value).
invalid_query400The query string failed to parse, references an unknown field, or uses a SQL feature we don’t accept.
unknown_signal404A signal name in the path does not exist. See the schema page for valid names.
not_found404The requested resource (ticker, webhook) was not found.
unauthorized401The Authorization header is missing or the API key is invalid.
forbidden403The API key is valid but does not include the requested capability (e.g. webhooks on the Reads tier).
rate_limited429You exceeded your plan's per-minute request limit. The `Retry-After` header indicates seconds to wait until the next minute boundary (always under 60s).
internal_error500Something went wrong on our side. Safe to retry with exponential backoff. Include the `request_id` if you contact support.

Rate limit

Per-key, per-minute window. The cap depends on your plan.

PlanPer-minute limitSustained equivalent
Reads100 / min~1.7 req/sec
Reads + Webhooks300 / min~5 req/sec
Enterprisecustom

The window is a rolling-minute bucket: brief bursts above the sustained rate are absorbed as long as you stay under your per-minute cap. When you cross the limit you get 429 rate_limited with a Retry-After header pointing at the next minute boundary (always under 60s).

Every successful response — and every 429 — includes rate-limit headers. Use them to back off proactively rather than waiting to be limited.

HeaderDescription
X-RateLimit-LimitPer-minute request limit for the API key (depends on plan: 100 on Reads, 300 on Reads + Webhooks).
X-RateLimit-RemainingRequests remaining in the current minute window.
X-RateLimit-ResetSeconds remaining until the per-minute window resets.
Retry-AfterSeconds to wait before retrying. Present only on 429 responses.

No daily cap. The per-minute window is what catches runaway clients; daily quotas mostly punish honest traffic without solving abuse. See authentication for the full plan comparison.

Backoff guidance

What to do when you get a 429.

  • Read the Retry-After header on the 429 response. Wait at least that many seconds before retrying.
  • Use exponential backoff for transient 5xx errors, starting at 1 second and doubling. Cap at 60 seconds.
  • Use the X-RateLimit-Remaining header to throttle yourself proactively rather than racing into the cap.
  • Treat internal_error (500) as retryable. Treatinvalid_request (400), invalid_query(400), and unauthorized (401) as fatal — retrying won't help.