Foreline/Docs
API · v1One 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.
From a key to a full ladder in three calls
GET /v1/health is the cheapest call in the API and confirms
the key, the clock and the service state.GET /v1/surface?event_id=… returns the main line, the fair
price, the measured margin and every rung of the ladder with its band.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.
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
403rather than an empty result — you always know the difference between “not permitted” and “nothing there”. - Usage:
GET /v1/usagereturns your consumption against the rpm and rpd quotas on the key, so you can alert on your own headroom instead of discovering it as429s.
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-off | Refresh cadence | data_cadence_s |
|---|---|---|
| Under 24 h | every 60 seconds | 60 |
| 24–96 h | every 5 minutes | 300 |
| Beyond 96 h | every 15 minutes | 900 |
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 class | Limit | Endpoints | Why |
|---|---|---|---|
| bulk | 4 / min | GET /v1/surface?since= |
A delta of full surfaces is a large object; four passes a minute already outruns a 60-second cadence. |
| point | 60 / min | /v1/surface (summary, event,
asof), POST /v1/score |
Sized for interactive use — a trading screen, a risk check at bet placement. |
| events | 12 / 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.
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.
Which call serves which product
| Product | Endpoints | Page |
|---|---|---|
| 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 |
| All | GET /v1/health, GET /v1/usage |
Reference |
Three statuses worth handling
| Status | Meaning | What to do |
|---|---|---|
401 | Missing, malformed or revoked key | Fix the header. Retrying will not help. |
403 | Authenticated, 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. |
429 | Per-class limit or account quota exceeded | Wait for Retry-After (seconds) and resume. Do not back off blindly —
the header tells you exactly when. |
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-proofs
—
python3 verify.pychecks 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.
Request a trial key
Keys are issued per contract — tell us which products, sports and history depth you need and we will scope one.
We usually reply within one business day. Pricing is quoted per scope — ask and we will send terms.
Foreline