Developer docs

Read the API in one page.

Introduction & envelope

Every dataset seekingdata serves is browsable from /catalog, for example crypto spot reference_price from binance, entityBTC-USD. Every data response, regardless of what it covers, is wrapped in the same three-part envelope:

{
  "data": "the requested payload: shape depends on the metric (scalar / object / series)",
  "meta": {
    "as_of": "2026-07-09T12:00:00.600Z",
    "venues": [
      "binance",
      "coinbase"
    ],
    "staleness_ms": 100,
    "confidence": 0.98
  },
  "provenance": {
    "sources": [
      {
        "venue": "binance",
        "ts": "2026-07-09T12:00:00.100Z"
      }
    ],
    "method": "outlier-trimmed cross-venue median"
  }
}
  • data: the payload itself; shape depends on the metric's value_shape (scalar, object, or series).
  • meta: as_of, venues, staleness_ms, a computed confidence (0 to 1); series responses add has_more, next_cursor, truncated, returned.
  • provenance: exact sources, timestamps, and the derivation method behind the number.

Authentication

seekingdata is invite-only: there's no self-serve signup. Navigation endpoints (catalog browsing) are public; data calls require an API key sent as either:

Authorization: Bearer $SEEKINGDATA_KEY

# or
X-API-Key: $SEEKINGDATA_KEY

Keys are long, prefixed random strings, shown once at creation (from /account), and are stored server-side as a salted hash. Losing one means regenerating, not recovering. A dedicated free-tier demo key ($SEEKINGDATA_KEY in the examples on this page) is baked into every example on this site so you can look around without an account; it shares the free-tier rate limit with every other visitor, so don't build on it.

The data endpoint

One shape for every metric, live or planned:

GET /v1/data/{category}/{product}/{metric}?entity=&source=&fields=&format=table&cursor=&max_response_tokens=

entity selects the instrument (e.g. BTC-USD); sourcefilters to one venue (omit for the combined/cross-venue value, where the metric supports one). A request for a planned metric returns 404 witherror_category: "not_yet_available", never a silent empty body.

Worked examples, one per live metric:

crypto/spot/reference_pricefree+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/crypto/spot/reference_price?entity=BTC-USD"

crypto/spot/ohlcvfree+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/crypto/spot/ohlcv?entity=BTC-USD"

crypto/spot/tradesbasic+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/crypto/spot/trades?entity=BTC-USD"

crypto/options/chainpro+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/crypto/options/chain?entity=BTC"

sports/tennis/resultsbasic+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/sports/tennis/results?entity="

sports/football/resultsbasic+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/sports/football/results?entity="

sports/basketball/resultsbasic+

curl -H "Authorization: Bearer $SEEKINGDATA_KEY" \
  "https://api.seekingdata.dev/v1/data/sports/basketball/results?entity="

Legacy single-metric routes (price, OHLCV, trades, options: one path segment per metric, no /data/ prefix) still work. They call the exact same resolver as the generic endpoint, so responses never drift.

Plans & limits

Rate limits are per key, per minute, enforced with a token bucket. The effective gate for a metric is max(product.min_tier, metric.min_tier).

PlanRate limitUnlocks
free10 req/minspot reference_price, spot ohlcv
basic60 req/min+ spot trades
pro300 req/min+ options chain
ultra1200 req/min+ everything, including all planned categories once they ship

Every response carries RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers, so an agent can back off before it gets throttled instead of after.

Errors

Failures come back as application/problem+json (RFC 9457): an agent can branch on error_category in code, not by parsing prose.

401 unauthorized: missing or invalid key

{
  "type": "https://seekingdata.dev/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Missing or invalid API key."
}

Agent reaction: stop and prompt for a key. Retrying won't help.

403 tier_forbidden: key valid, plan too low

{
  "type": "https://seekingdata.dev/errors/tier-forbidden",
  "title": "Tier forbidden",
  "status": 403,
  "detail": "crypto/options/chain requires the pro plan or higher.",
  "error_category": "tier_forbidden"
}

Agent reaction: surface the upgrade path (/account) instead of retrying.

429 rate_limit: over the plan's requests/min

{
  "type": "https://seekingdata.dev/errors/rate-limit",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "10 requests/min exceeded for the free plan.",
  "error_category": "rate_limit",
  "retryable": true,
  "retry_after": 42
}

Agent reaction: back off for retry_after seconds, then retry. retryable: true makes this safe to automate.

A request for a planned metric returns 404 with error_category: "not_yet_available", distinct from a routing 404, so an agent knows the path is right and the data just isn't collected yet.

Pagination & fields

Series-shaped metrics (candles, trades) support:

ParamEffect
fieldsComma-separated allowlist: trims the response to just the columns you need.
format=tableColumnar `{columns, rows}` instead of an array of objects, smaller on the wire for wide series.
cursorOpaque pagination cursor from meta.next_cursor.
max_response_tokensTruncates to whole rows (never mid-object) and sets meta.truncated + a one-line meta.hint.

MCP

The same catalog and envelope are exposed as typed MCP tools:

claude mcp add seekingdata --env SEEKINGDATA_API_KEY=<key> -- npx -y @seekingdata/mcp

browse_catalog and get_metric are the generic navigation and data escape hatches; reference_price, ohlcv,recent_trades, and option_chain are crypto conveniences that call get_metric internally. Missing, invalid, or under-tier keys come back as typed, actionable MCP errors, not a stack trace.

Machine-readable

GET /openapi.jsonOpenAPI 3.1 contract, generated from the live catalog + resolver registry: includes the auth scheme and 401/403/429 response shapes.
GET /llms.txtA plain-text orientation doc for LLMs that land on the API without an MCP connection.
GET /.well-known/seekingdata.jsonThis site's agent descriptor: catalog summary, MCP install command, contact.