RaceHooks for Research & Teaching

Seven decades of racing,
one consistent schema.

Results, qualifying, laps, stints, pit stops, standings, and weather from 1950 onward — one schema, canonical driver and constructor identity throughout, and a free tier that stays free. Cite an endpoint instead of a scraped CSV nobody else can reproduce.

Everything on this page ships on Developer$99/mo, self-serve.
Lap-level records
historical/:season/:round/lapsROW-LEVEL · 1950 →
CarLapPosTimeCompound
VER1P11:33.402MEDIUM
LEC1P21:34.117MEDIUM
NOR1P31:34.640HARD
PIA1P41:35.008HARD
01 · What you build

What researchers and students build on RaceHooks

Reproducible datasets for papers

A reviewer can re-run your data collection because it is an HTTP request against a stable schema, not a scraper against a page that has since changed. Driver and constructor identity is canonical across every season, so a merge across eras does not silently mismatch on a renamed team.

Built from
historical/seasonshistorical/:season/:round/resultshistorical/:season/:round/laps

Teaching datasets & student projects

A course needs data that is interesting, well-shaped, and available on the first evening without a procurement conversation. Lap times, stints, and pit stops across seven decades are enough for a term of regression, time-series, survival analysis, or classification work.

Built from
historical/:season/:round/lapshistorical/:season/:round/pitstopshistorical/:season/driverStandings

ML training corpora

Lap-level records with the context that makes them modellable — compound and tyre age, weather on the same clock, and the classification each session ended in. Enough structure to train on without spending the first month reconciling identities.

Built from
historical/:season/:round/stintshistorical/:season/:round/weatherdata/circuits

Sports science & engineering studies

Reliability by constructor, career trajectories by driver, circuit-by-circuit records, and per-round weather — the joins a study usually spends its first month building, already made and already keyed.

Built from
historical/constructors/:constructorId/reliabilityhistorical/drivers/:driverId/careerhistorical/circuits
02 · What your users see

One payload, straight onto the screen

What a research use of this actually looks like: a table you can join, a record you can cite, and the identity contract that makes both safe.

Why it reproduces
REQUESTThe collection step is one HTTP call
Not a scraper against a page that has since been redesigned. The request in your methods section still runs.
SCHEMAThe same shape across every season
1950 and 2026 return the same fields, so a cross-era panel does not need a per-decade special case.
IDENTITYCanonical driver and constructor ids
A team that renamed itself keeps one constructorId, so a merge does not silently split it into two entities.
Free tier, permanently — no card, no expiry Cite the endpoint and the access date; both stay valid.

The difference between a dataset a reviewer can re-derive and one they have to take on trust is entirely in these three steps.

Where the free tier ends
# limits
RH
racehooksAPP$0
FREE — the historical archive
Results, qualifying, laps, stints, pit stops, standings, weather. No expiry.
RH
racehooksAPP$0
FREE — live session state
Session status, track status, lap count, driver list, and weather during a session.
RH
racehooksAPPstep up
DEVELOPER — when a project gets users
The full live catalog by webhook or SSE, a larger delivery bucket, higher rate limits, and per-lap telemetry from completed sessions — the level below lap times.

Stated up front rather than discovered at a rate limit. Everything a study needs from the archive is on the free tier; the paid step is about live delivery volume, not about access to history.

↑ all of it, from this payload
GET /v1/historical/2024/1/laps — one request, a stable schema
{
  "season": 2024,
  "round": 1,
  "laps": [
    {
      "lap": 1,
      "driverId": "verstappen-max",
      "constructorId": "red-bull",
      "position": 1,
      "time": { "display": "1:33.402", "ms": 93402 }
    }
  ]
}

# driverId and constructorId are canonical and stable across seasons — the same
# ids the live feeds use. A join across eras keys on those, never on a name string.

Example interfaces, rendered from the fields above — your product, your design system. Nothing here is a template you have to adopt.

03 · Endpoints

The endpoints that build it

Every route is Bearer-authenticated and versioned under /v1. Base URL https://api.racehooks.io/v1.

MethodPathWhat it gives you
GET/v1/historical/seasonsEvery season in the archive — the index a collection script starts from.
GET/v1/historical/:season/:round/resultsFinal classification for a round, with qualifying, sprint, and practice on sibling routes.
GET/v1/historical/:season/:round/lapsLap-by-lap times for a session — the row-level table most studies are actually built on.
GET/v1/historical/:season/:round/stintsCompound and stint plan per driver, with pitstops and weather on sibling routes for the same round.
GET/v1/historical/drivers/:driverId/careerA driver's full career record; the constructors routes carry the equivalent, including reliability by season.
GET/v1/historical/circuitsCanonical circuit identity and the rounds each has held — the key a cross-era join needs.
Feeds you subscribe to
session.statusSession lifecycle — started, aborted, finished, finalised. Free, and enough to timestamp a collection run.
session.track-statusGreen, yellow, safetyCar, red — one named status. Free, and the covariate most race models want.
session.lap-countCurrent lap and laps remaining. Free.
driver.listNumber, TLA, full name, team and team colour — the canonical identity every other payload keys to. Free.
weather.dataAir and track temperature, humidity, pressure, wind, and rainfall. Free, and on the same clock as the laps.
timing.dataPosition, gaps, lap and sector times, live. The Developer step up, when a study needs the session as it runs.

Developer includes all 30 live data feeds, not just the ones above; the remaining 25 in the 55-feed catalog are the Custom analytics feeds. Every id, cadence, and payload schema is documented.

04 · Delivery

Three ways the data reaches you

Pick per integration — you can run all three against one API key. Webhook and SSE frames both meter against your monthly delivery bucket; REST reads meter against the request rate limit instead.

Webhook

Push · default

Register an HTTPS endpoint and subscribe it to feeds. RaceHooks POSTs each event as it fires — typically well within a second. Every payload is HMAC-SHA256 signed, retried with exponential backoff on failure, and every attempt is logged in your console with headers, status, and latency.

POST /v1/webhooks
{ "webhookUrl": "https://your-app.com/hook",
  "feedId": "events.race" }
Best for: Server-side apps, scoring engines, alerting.

SSE stream

Push · no public URL

Open one long-lived connection and read frames as they arrive — no public webhook server to host or expose. Each frame is `event: <feedType>` + a JSON `data:` line, with a ping every 30s so proxies hold the connection open. Auth by Bearer header, or `?token=` for browser EventSource, which cannot set headers.

GET /v1/stream?feeds=raceevent,timingdata
Authorization: Bearer $TOKEN
Best for: Local development, dashboards, browser clients.

REST

Pull · on demand

Query completed and reference data directly whenever you need it — results, standings, laps, stints, pit stops, and the segment endpoints above. Use it to backfill history, hydrate a new user, or reconcile after an outage rather than to follow a live session.

GET /v1/historical/2026/16/results
Authorization: Bearer $TOKEN
Best for: Backfill, reference data, reconciliation.
05 · Before race day

Test the whole thing on a quiet Tuesday

Simulate replays a real current-season session through your own webhooks at any speed from 0.1× to 120×. Your integration receives the exact payloads it would in a live race — real data, known result — so you can validate research logic end to end before a live session ever runs. Free includes 5 sessions, Developer 10; Custom replays the full archive.

How Simulate works →
Upgrade · Custom tier

What the ML layer adds for research

The archive above is free and stays free. Custom exists for work that needs the modelled layer or the raw channels underneath it — normally a lab with a grant, an industrial partner, or a licensing question. On Custom, fourteen production ML models attach an analytics key to every payload you already receive — same feeds, same delivery, same code path.

Mini-sector timing

timing.mini-sectors is the high-granularity companion to lap timing — mini-sector progress ticks and speed-trap detail, for work where a lap is too coarse a unit.

Model outputs as a comparison baseline

The analytics feeds carry our own fitted surfaces — position distributions, true pace, tyre state — which is the honest thing to benchmark a new method against rather than a naive baseline.

Full-archive replay

Self-serve replay is capped at distinct current-season sessions. Custom lifts it to the whole archive, which matters when the object of study is the sequence rather than the table.

Talk to salesRead the model methodology →Custom also adds a delivery SLA, unlimited deliveries, and full-archive replay.

Start on the free tier.

Build and test a complete integration on historical and replayed sessions — no credit card. Go Developer when you need it live.

Start buildingCompare plans