Foreline/Docs

API · v1

One key, one base URL, four delivery shapes

Everything Foreline publishes is reachable over HTTPS from https://api.foreline.io with a single header. This page gets you to a first response; the reference documents every endpoint, parameter and field.

API reference → No self-service signup: keys are issued per contract. Ask us for a trial key.
Quickstart

From a key to a full ladder in three calls

Check you are authenticated GET /v1/health is the cheapest call in the API and confirms the key, the clock and the service state.
Read one event in full GET /v1/surface?event_id=… returns the main line, the fair price, the measured margin and every rung of the ladder with its band.
Stay in sync GET /v1/surface?since=… returns everything that changed since your cursor and hands back next_since for the following call. That is the whole loop — no pagination state to keep on your side.
# 1 — health
curl -s "https://api.foreline.io/v1/health" \
  -H "X-Foreline-Key: $FORELINE_KEY"

{ "status": "ok", "server_ts": "2026-07-24T18:41:07Z", "version": "v1" }

# 2 — one event, full ladder
curl -s "https://api.foreline.io/v1/surface?event_id=EVT_8F3A21" \
  -H "X-Foreline-Key: $FORELINE_KEY"

# 3 — bulk delta, then repeat with the returned next_since
curl -s "https://api.foreline.io/v1/surface?since=2026-07-24T18:40:00Z" \
  -H "X-Foreline-Key: $FORELINE_KEY"

Values in examples throughout the docs are illustrative.

Authentication

One header, one key per environment

  • Header: X-Foreline-Key: <your key> on every request, including the SSE stream. There is no OAuth dance and no token exchange.
  • Transport: HTTPS only. Requests without the header, or with a key that has been revoked, return 401.
  • Scope: a key carries the products, sports and history depth in your contract. A call to something outside that scope returns 403 rather than an empty result — you always know the difference between “not permitted” and “nothing there”.
  • Usage: GET /v1/usage returns your consumption against the rpm and rpd quotas on the key, so you can alert on your own headroom instead of discovering it as 429s.
Cadence & polling

The data moves once a minute, so the limits are shaped around that

Our rate limits are not a monetisation device; they follow from how often the underlying data actually changes. Polling faster than the cadence returns the same bytes with the same updated_ts.

Time to kick-offRefresh cadencedata_cadence_s
Under 24 hevery 60 seconds60
24–96 hevery 5 minutes300
Beyond 96 hevery 15 minutes900

Every response carries data_cadence_s — the interval that applies to that object right now. Schedule your next call off that field and your poller stays correct when an event crosses a cadence boundary, without you tracking kick-off times.

Call classLimitEndpointsWhy
bulk4 / minGET /v1/surface?since= A delta of full surfaces is a large object; four passes a minute already outruns a 60-second cadence.
point60 / min/v1/surface (summary, event, asof), POST /v1/score Sized for interactive use — a trading screen, a risk check at bet placement.
events12 / min/v1/line-events, /v1/alerts Catch-up polling. For live delivery use the SSE stream or a webhook instead of polling harder.

Quotas are per client: an rpm (requests per minute) and an rpd (requests per day) ceiling on the key, on top of the per-class limits above. Both are visible from GET /v1/usage. Exceeding either returns 429 with a Retry-After header — respect it and you will not be throttled further.

Delivery shapes

Four ways to receive the same facts

Most integrations use two: a bulk delta to keep a local mirror warm, and a stream or webhook for the moments that matter.

Point read

One object, right now or as of a past timestamp. GET /v1/surface?event_id= and ?asof=. Use it for screens, for a risk check at placement, and for settling a dispute about what was published when.

Bulk delta

Everything that changed since your cursor, as full surfaces: GET /v1/surface?since=, with next_since in the response. This is the backbone of a local mirror — no diff logic on your side.

Server-sent events

A held connection on GET /v1/stream emitting event: line_change as main-line moves are detected. Reconnect with your last cursor on /v1/line-events?since= and you lose nothing across a restart.

Webhook

Push delivery to your endpoint for alerts and line events, signed with X-Foreline-Signature: sha256=… — an HMAC over the raw body with your shared secret. Verify before you act.

Endpoints by product

Which call serves which product

ProductEndpointsPage
Fair-Price Surface GET /v1/surface — summary, ?event_id=, ?asof=, ?since= Fair-Price Surface
Player Radar POST /v1/score Player Radar
Line Radar GET /v1/line-events, GET /v1/stream, GET /v1/alerts, webhook Line Radar
Parlay Protection Marginals from GET /v1/surface; joint pricing delivered as an audit first, then as a feed scoped by contract Parlay Protection
AllGET /v1/health, GET /v1/usage Reference
Errors

Three statuses worth handling

StatusMeaningWhat to do
401Missing, malformed or revoked key Fix the header. Retrying will not help.
403Authenticated, but outside the scope of your contract — a sport, product or history depth you do not hold Treat as a permanent answer for that call; talk to us if the scope is wrong.
429Per-class limit or account quota exceeded Wait for Retry-After (seconds) and resume. Do not back off blindly — the header tells you exactly when.

Full error reference →

Verifiability

Check the data before you integrate it

The proof layer is public and needs neither a key nor an NDA — you can audit the record before you write a line of client code.

  • Hash chain and Merkle commitments. Every published row is chained; every pass is committed; the daily roots are anchored in Bitcoin via OpenTimestamps. Rows cannot be edited or selectively dropped after the fact.
  • Public verifier: github.com/foreline-io/foreline-proofspython3 verify.py checks the daily roots, the commitment chain and the Bitcoin stamps.
  • Tamper-evident from 23 July 2026. As-of history reaches further back — football from 2022 — and rows predating the ledger are served as archive, labelled as such.

Go to the API reference →

Access

Request a trial key

Keys are issued per contract — tell us which products, sports and history depth you need and we will scope one.

Email us

We usually reply within one business day. Pricing is quoted per scope — ask and we will send terms.

Request trial