LIVEDATASET2026.w1.11SEASON2026 · WK 1BUILT2026-08-25 12:35Z
API REFERENCE · V1

The whole product, over HTTP.

Read this without an account: it is the contract an engineer evaluates before anyone pays. The base URL is https://apexdatum.io, every response is JSON unless you asked for CSV, and the envelope below is stable - fields are added, never renamed or removed within v1.

Quickstart

Three requests tell you most of it

The first works right now, from this page, with no account.

# reproducibility metadata - free, no auth, at every tier
curl https://apexdatum.io/api/v1/manifest

# the catalog, annotated with what your key can read
curl -H "Authorization: Bearer ep_live_..." https://apexdatum.io/api/v1/packages

# one package, every dataset in it, gated by your plan
curl -H "Authorization: Bearer ep_live_..." https://apexdatum.io/api/v1/packages/td-equity
Authentication

An opaque key that names you, and asserts nothing

Created and revoked on your account page. API access is part of the Feed plan.

  • Keys look like ep_live_... and encode no tier, no plan and no expiry. Your entitlement is computed fresh on every request, so changing plans changes what a key reads without rotating it - and a leaked key cannot be edited into a better one, because it asserts nothing.
  • We store a keyed hash, not the key. It is shown exactly once at creation; revocation is immediate; up to five keys can be active per account.
  • Send it in the Authorization: Bearer header, never in a URL. Query strings land in server logs, browser history and referrers; headers do not.
  • Server-side only. The API sends no CORS headers, deliberately: a browser page cannot call it cross-origin, because an API key shipped in client-side JavaScript is a published key. Call it from your backend, notebook or pipeline.
Rate limits

5,000 requests per key, per UTC day

Counted atomically, reported on every response.

X-RateLimit-Limit      5,000     your effective daily allowance
X-RateLimit-Remaining  what is left today
X-RateLimit-Used       requests counted, including any rejected over the limit
X-RateLimit-Reset      unix seconds - the next UTC midnight
X-RateLimit-Degraded   present only if the counter was unreadable and we let you through

429 carries Retry-After. Rejected requests still count, deliberately -
otherwise a client can hammer a closed door for free. If the quota counter
itself is unavailable the request is allowed rather than refused, and says so:
you are already authorised at that point, and breaking a paid product to
defend a fair-use ceiling is the wrong trade.
Endpoints

The v1 surface, complete

Every v1 API endpoint, with its method, path, authentication requirement and what it returns
MethodPathAuthReturns
GET/api/v1/manifestnoneDataset version, source SHA-256 digests, stated limits - the reproducibility claim, free so it stays checkable
GET/api/v1/packageskeyThe catalog, annotated with what your key can read
GET/api/v1/packages/{packageId}keyOne package: every dataset it contains, gated per dataset by your plan
GET/api/v1/export?format=csv|json[&package=id,id]key + FeedEverything you are entitled to, one file per (package, dataset)
GET/api/v1/export/{packageId}?format=csv|jsonkey + FeedOne package as files
GET/api/v1/releasesnone for metadataEvery archived release version
GET/api/v1/releases/{version}[?dataset=name]key + Feed for bodiesA pinned release: metadata free, byte-identical dataset bodies on the Feed plan
GET/api/v1/as-of/{source}?at=<ISO8601>[&body=1]key + Feed for bodiesPoint-in-time: what a source said at any past instant. Metadata free; bodies on the Feed plan

Export formats: csv, json. XLSX and Parquet are not served - a format we cannot round-trip byte-identically through the release archive would break the reproducibility promise the archive exists to make, so we publish the two we can prove rather than the four that would demo well.

Responses

One envelope, one error shape

Package responses carry the data, your access to it, and the exact build it came from.

{
  "package":  { "id", "number", "name", "parameters", "limits" },
  "access":   { "tierId", "tierNumber", "level", "redactedFields", "upgrade" },
  "dataset":  { "version", "season", "week", "generatedAt" },
  "meta":     { "<dataset>": { "totalRows", "returnedRows", "truncated" } },
  "datasets": { "<dataset>": [ ... ] },
  "disclaimer": "..."
}
Every API error response, with its HTTP status, error code and meaning
StatusCodeMeaning
400missing_at / bad_atas-of requires an explicit ?at - an endpoint that silently answers “latest” is not point-in-time
401unauthorizedOne message for malformed, unknown and revoked keys, deliberately - the response does not reveal which
402api_not_in_planYour plan has no API. Scout and Active are read-on-site by design
403access_deniedThat package is not in your plan; the body names the tier that opens it
404unknown_packageAnswered before authentication, and the body lists valid ids - the package list is public, so hiding it protects nothing
429rate_limitedDaily quota exhausted; carries Retry-After. Rejected requests still count - a closed door is not free to hammer
500server_errorOurs, not yours
Packages

What each plan's key can read

Generated from the same grant object the API enforces - this table cannot promise what the engine does not gate.

Every package, with the level of access each plan's API key has to it
#PackageEndpoint idScoutActiveFeed
01Positional Stat Linesstat-lines
02Injury & Availability Intelinjury-intel
03Market Divergence Boardmarket-divergence
04Licensed Data Accesslicensed-data
05Touchdown Equitytd-equity
06Draft Value Enginedraft-value
07Draft Availability Simulatoravailability-sim
08Game Forecastgame-forecast
09Verification Ledgerverification
10Leg Correlation Matrixleg-correlations
11Outcome Boardoutcome-board
12NHL Game Forecastnhl-game-forecast
13The Weekly Boardweekly-board
full access every row, some columns hidden not includedAPI ACCESS REQUIRES THE FEED PLAN
Reproducibility

Version-pinned, hash-verified, point-in-time

Every release is archived under an immutable version with the SHA-256 of each upstream source. Ask /api/v1/releases/{version} for a version you used last month and the bytes come back identical - that is the claim CI re-proves on every push, not a marketing line. /api/v1/as-of answers what a source said at any past instant, which is what makes a backtest honest: the data your model saw, not the data as it was later corrected.

Read before integrating
  • We publish probabilities and ranges, never picks, stakes or EV figures - at any tier, over any endpoint. If your integration needs a wagering recommendation, this API will not produce one.
  • No webhooks and no change notifications yet. Poll the manifest; its generatedAt changes when the data does.