Feed CatalogAnalytics

Analytics

analytics

12 independently-subscribable analytics.* feeds plus driverscore — the real-time outputs of 12 production ML models and the algorithmic layer on top of them. Each feed answers one question and is delivered as its own stream, so you subscribe to exactly what your product needs. For how each model is built and calibrated, see the Models reference →

bash
# SSE — stream two analytics feeds together
curl -H "Authorization: Bearer $TOKEN" \
  "https://api.racehooks.io/v1/stream?feeds=analytics.strategy,analytics.race-odds"

# Webhook — register analytics.race-odds for a driver filter
curl -X POST "https://api.racehooks.io/v1/webhooks" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"feedId":"analytics.race-odds","webhookUrl":"https://example.com/hook","filters":{"driverNumbers":["1","4"]}}'
The driverNumbers filter works on analytics.strategy, analytics.race-odds, analytics.gap-projection, analytics.tire-strategy, and analytics.qualifying. For analytics.constructor the payload is small (10 constructors) — no filter needed.
Feed IDTierCadenceDescription
driverscoreanalyticsPer updateRelative 1–10 driver performance scores (brake, throttle, g-force).
analytics.strategyanalyticsPer lapPer-driver strategy signals: pit stop probability, undercut threat, pace mode, tire health, DNF risk; plus session-level safety car probability.
analytics.race-oddsanalyticsPer lapCTMC position distribution, podium/points odds, expected points, fastest-lap probability, H2H vs teammate, plus same-team pairs.
analytics.gap-projectionanalyticsPer lapProjected gap to the race leader at race end for every driver: five percentile bands (p10–p90) plus P(lapped) from Monte Carlo simulation.
analytics.tire-strategyanalyticsPer pit approachNext-compound probabilities for drivers approaching a pit window (pitStopProbability > 0.25). Sparse — fires only when relevant.
analytics.constructoranalyticsPer lapConstructor-level expected points from discrete joint position-distribution convolution, with P(both drivers score) and full points distribution.
analytics.championship-probabilityanalyticsOnce, post-racePost-race championship win probability for all drivers. afterRaceId identifies which race the data reflects.
analytics.qualifyinganalyticsPer lap improvementPer-sector fastest probabilities and per-driver pace deltas during qualifying, with pole-margin probability. Fires after each personal best.
analytics.sector-paceanalyticsOn sector anomalyPer-sector pace deltas with anomaly detection; fires when a sector-pace anomaly is detected.
analytics.battleanalyticsOn battle state changeOn-track battle status between a driver and the car directly ahead (closing, holding, defending).
analytics.pit-windowanalyticsOn window open/urgentPit-window status (OPEN / URGENT) combining pit probability, undercut viability, tyre cliff risk, and gap context.
analytics.track-conditionsanalyticsPer lapTrack evolution and grip-condition analytics derived from field pace trends.
analytics.pit-qualityanalyticsOn pit completionPit-stop execution quality assessment (stationary time vs. expected) after a stop completes.

Subscribe with the feedId via webhook or SSE. Tier shown is the minimum plan required.

driverscoreDriver Scoreanalytics

Per update

Relative 1–10 driver performance scores (brake, throttle, g-force).

analytics.strategyRace Strategy Analyticsanalytics

Per lap · Race, Sprint

Per-driver strategy signals: pit stop probability, undercut threat, pace mode, tire health, DNF risk; plus session-level safety car probability.

Backed by: pit_stop_tele_bilstm, overtake_xgboost, undercut_lgbm, ltoe_lgbm, safety_car_lgbm, pit_stop_count_lgbm, dnf_risk, pace_mode, EKF tire health, competitor intelligence. How the models work →

FieldTypeDescription
regulationsErastring"2026" or "pre-2026". All 2026 models have era-specific calibration applied.
safetyCarProbabilitynumberP(any SC/VSC deployment next lap). Session-level — same value for all drivers. LightGBM + Hawkes-process over historical incident data.
vscProbabilitynumber|nullP(virtual SC specifically). null when the 3-class SC model is not loaded.
fullScProbabilitynumber|nullP(full safety car). null when the 3-class SC model is not loaded.
competitorIntelligenceobjectField-level pit-window estimates. Omitted for the first few laps before the engine has data.
drivers[].pitStopProbabilitynumber0–1. BiLSTM probability of a pit stop this lap, over a 20-lap feature window.
drivers[].pitRecommendedbooleantrue when pitStopProbability ≥ session threshold (era-adjusted: 0.53 pre-2026, 0.60 for 2026).
drivers[].overtakeProbabilitynumber0–1. XGBoost probability of a position gain via overtake within 3 laps. Circuit overtake index applied.
drivers[].undercutThreatobjectPresent when the car ahead is within the strategic gap threshold: score, viable, gapToCarAheadSec, estimatedDeltaSec, probability.
drivers[].paceModestring"PUSH" | "HOLD" | "MANAGE" | "WARM_UP" | "DELTA". Lap-time variance and LTOE-based pace classification.
drivers[].ltoeobjectLap Time Over Expected: ltoeSec (negative = faster than expected), expectedLapTimeSec, actualLapTimeSec, confidenceScale.
drivers[].tireHealthobjecttireHealth (0–1), degRateSecPerLap, stintLap. Derived from a Kalman filter on the lap-delta series.
drivers[].dnfRiskobjectdnfRiskScore (0–1 bathtub hazard), constructorHazardRate, lapsTo50PctSurvival.
Sample payload
json
{
  "feed": "analytics.strategy",
  "sessionId": "9560",
  "raceId": "2026-monaco-r1",
  "lap": 35,
  "utc": "2026-06-08T14:32:18.441Z",
  "regulationsEra": "2026",
  "safetyCarProbability": 0.08,
  "vscProbability": 0.04,
  "fullScProbability": 0.04,
  "drivers": [
    {
      "driverNumber": "4",
      "driverId": "norris-lando",
      "pitStopProbability": 0.79,
      "pitRecommended": true,
      "overtakeProbability": 0.12,
      "paceMode": "PUSH",
      "ltoe": {
        "ltoeSec": -0.182,
        "expectedLapTimeSec": 87.594,
        "actualLapTimeSec": 87.412,
        "confidenceScale": 0.75
      },
      "ltoeConfidenceFlag": "2026_early",
      "tireHealth": {
        "tireHealth": 0.58,
        "degRateSecPerLap": 0.041,
        "stintLap": 14
      },
      "dnfRisk": {
        "dnfRiskScore": 0.012,
        "lapsTo50PctSurvival": null,
        "constructorHazardRate": 0.018
      }
    },
    {
      "driverNumber": "1",
      "driverId": "verstappen-max",
      "pitStopProbability": 0.06,
      "pitRecommended": false,
      "overtakeProbability": 0.34,
      "undercutThreat": {
        "score": 0.71,
        "viable": true,
        "gapToCarAheadSec": 4.218,
        "estimatedDeltaSec": 1.8,
        "probability": 0.62
      },
      "paceMode": "HOLD",
      "ltoe": {
        "ltoeSec": 0.048,
        "expectedLapTimeSec": 88.055,
        "actualLapTimeSec": 88.103,
        "confidenceScale": 0.75
      },
      "ltoeConfidenceFlag": "2026_early",
      "tireHealth": {
        "tireHealth": 0.91,
        "degRateSecPerLap": 0.018,
        "stintLap": 8
      },
      "dnfRisk": {
        "dnfRiskScore": 0.009,
        "lapsTo50PctSurvival": null,
        "constructorHazardRate": 0.021
      }
    }
  ]
}

analytics.race-oddsRace Outcome Probabilitiesanalytics

Per lap · Race, Sprint

CTMC position distribution, podium/points odds, expected points, fastest-lap probability, H2H vs teammate, plus same-team pairs.

Backed by: CTMC win probability, fastest_lap_xgboost. How the models work →

FieldTypeDescription
drivers[].positionDistributionnumber[20]20-element CTMC probability vector. Index 0 = P(finish 1st). Sums to ≤1.0 (lower for retired drivers).
drivers[].mostLikelyPositionnumber1-based index of the highest-probability position slot.
drivers[].podiumProbabilitynumberP(finish P1–P3). Sum of positionDistribution[0..2].
drivers[].top10ProbabilitynumberSum of positionDistribution[0..9]. Equivalent to P(score points).
drivers[].expectedPointsnumberExpected F1 points from the distribution × points structure, plus fastest-lap bonus weighted by fastestLapProbability.
drivers[].lapsLedExpectednumberExpected race laps led from the current position. CTMC forward integration.
drivers[].fastestLapProbabilitynumberL1-normalised P(set the session fastest lap). Field sums to 1.0.
drivers[].positionChangeobjectCTMC forward projection at next3Laps/next5Laps/next10Laps: gainAtLeast1, loseAtLeast1, holdPosition.
drivers[].h2hVsTeammatenumber|nullP(this driver finishes ahead of team-mate). null when team-mate has no distribution.
pairs[]object[]Same-team H2H pairs: constructorId, driverA/B, pABeatsB, pBBeatsA, pTie.
Sample payload
json
{
  "feed": "analytics.race-odds",
  "sessionId": "9560",
  "raceId": "2026-monaco-r1",
  "lap": 35,
  "utc": "2026-06-08T14:32:18.441Z",
  "drivers": [
    {
      "driverNumber": "4",
      "driverId": "norris-lando",
      "position": 1,
      "positionDistribution": [
        0.47,
        0.25,
        0.16,
        0.07,
        0.03,
        0.01,
        0.01,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "mostLikelyPosition": 1,
      "podiumProbability": 0.88,
      "top6Probability": 0.97,
      "top10Probability": 0.99,
      "expectedPoints": 18.9,
      "pointsFinishProbability": 0.99,
      "lapsLedExpected": 24.1,
      "fastestLapProbability": 0.28,
      "positionChange": {
        "next3Laps": {
          "gainAtLeast1": 0.03,
          "loseAtLeast1": 0.08,
          "holdPosition": 0.89
        },
        "next5Laps": {
          "gainAtLeast1": 0.05,
          "loseAtLeast1": 0.13,
          "holdPosition": 0.82
        },
        "next10Laps": {
          "gainAtLeast1": 0.08,
          "loseAtLeast1": 0.21,
          "holdPosition": 0.71
        }
      },
      "h2hVsTeammate": 0.61
    },
    {
      "driverNumber": "1",
      "driverId": "verstappen-max",
      "position": 2,
      "positionDistribution": [
        0.38,
        0.28,
        0.19,
        0.09,
        0.04,
        0.01,
        0.01,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "mostLikelyPosition": 1,
      "podiumProbability": 0.85,
      "top6Probability": 0.96,
      "top10Probability": 0.99,
      "expectedPoints": 17.1,
      "pointsFinishProbability": 0.99,
      "lapsLedExpected": 18.4,
      "fastestLapProbability": 0.41,
      "positionChange": {
        "next3Laps": {
          "gainAtLeast1": 0.11,
          "loseAtLeast1": 0.06,
          "holdPosition": 0.83
        },
        "next5Laps": {
          "gainAtLeast1": 0.17,
          "loseAtLeast1": 0.1,
          "holdPosition": 0.73
        },
        "next10Laps": {
          "gainAtLeast1": 0.26,
          "loseAtLeast1": 0.16,
          "holdPosition": 0.58
        }
      },
      "h2hVsTeammate": 0.39
    }
  ],
  "pairs": [
    {
      "constructorId": "mclaren",
      "driverA": "4",
      "driverAId": "norris-lando",
      "driverB": "81",
      "driverBId": "piastri-oscar",
      "pABeatsB": 0.61,
      "pBBeatsA": 0.38,
      "pTie": 0.01
    }
  ]
}

analytics.gap-projectionGap to Leader Projectionanalytics

Per lap · Race, Sprint

Projected gap to the race leader at race end for every driver: five percentile bands (p10–p90) plus P(lapped) from Monte Carlo simulation.

Backed by: Monte Carlo gap projection. How the models work →

FieldTypeDescription
drivers[].currentGapToLeaderSecnumberCurrent gap to the race leader (seconds).
drivers[].expectedGapToLeaderSecnumberMonte Carlo mean projected gap at race end.
drivers[].p10GapSecnumber10th-percentile projected gap — optimistic scenario.
drivers[].p50GapSecnumberMedian projected gap.
drivers[].p90GapSecnumber90th-percentile projected gap — pessimistic scenario.
drivers[].probabilityLappednumberP(driver is lapped by race end). Typically < 0.05 for active drivers.

analytics.tire-strategyTire Strategy Probabilityanalytics

Per pit approach · Race, Sprint

Next-compound probabilities for drivers approaching a pit window (pitStopProbability > 0.25). Sparse — fires only when relevant.

Backed by: tire_compound_lgbm. How the models work →

FieldTypeDescription
drivers[].pitProbabilitynumberCurrent pit-stop probability from the BiLSTM model.
drivers[].nextCompoundProbability.softnumberP(next compound = soft).
drivers[].nextCompoundProbability.mediumnumberP(next compound = medium).
drivers[].nextCompoundProbability.hardnumberP(next compound = hard).
drivers[].nextCompoundProbability.internumberP(intermediates). Elevated when a weather event is approaching.
drivers[].nextCompoundProbability.wetnumberP(wets).

analytics.constructorConstructor Points Analyticsanalytics

Per lap · Race, Sprint

Constructor-level expected points from discrete joint position-distribution convolution, with P(both drivers score) and full points distribution.

Backed by: CTMC win probability, constructor points convolution. How the models work →

FieldTypeDescription
constructors[].constructorIdstringTeam identifier (e.g. "red-bull", "ferrari", "mclaren").
constructors[].expectedConstructorPointsnumberExpected combined points from both drivers, via discrete convolution of joint position distributions — analytically exact.
constructors[].scoringBothDriversProbabilitynumberP(both drivers finish top 10). Joint probability from the distribution product.
constructors[].pointsDistributionnumber[]P(team scores exactly K combined points) for K = 0…44.

analytics.championship-probabilityChampionship Win Probabilityanalytics

Once, post-race · Season

Post-race championship win probability for all drivers. afterRaceId identifies which race the data reflects.

Backed by: season simulator (infer_scwp). How the models work →

FieldTypeDescription
afterRaceIdstringThe race this data reflects — may run slightly after processPostRaceTelemetry.
seasonnumberChampionship season year.
drivers[].championshipProbabilitynumberP(this driver wins the WDC). Field sums to ≤1.0.
drivers[].currentPointsnumberPoints standing after afterRaceId.
drivers[].pointsGapnumberPoints gap to the championship leader (negative = trailing).

analytics.qualifyingQualifying Analyticsanalytics

Per lap improvement · Qualifying

Per-sector fastest probabilities and per-driver pace deltas during qualifying, with pole-margin probability. Fires after each personal best.

Backed by: qualifying_pace_s1/s2/s3_lgbm, conformal qualifying distribution. How the models work →

FieldTypeDescription
segmentstringActive segment: "Q1", "Q2", or "Q3".
poleLeaderstringDriver number currently projected to take pole (lowest sum of sector deltas).
poleMarginAbove100msnumberP(gap between pole and P2 > 0.1s). From the conformal-calibrated margin model.
sectors.s1.drivers[].pFastestnumberP(this driver sets fastest S1). L1-normalised across drivers with pace data.
sectors.s1.drivers[].predictedDeltaMsnumberPredicted S1 delta vs. session median (ms). Negative = faster.
drivers[].sector1DeltaMsnumber|nullPredicted S1 delta vs. session median (ms). null when the qualifying pace model is not loaded.
Sample payload
json
{
  "feed": "analytics.qualifying",
  "sessionId": "9560",
  "raceId": "2026-monaco-r1-q",
  "utc": "2026-06-08T14:32:18.441Z",
  "segment": "Q3",
  "circuitKey": "monaco",
  "poleMarginAbove100ms": 0.71,
  "poleMarginAbove300ms": 0.31,
  "poleLeader": "1",
  "sectors": {
    "s1": {
      "drivers": [
        {
          "driverNumber": "1",
          "driverId": "verstappen-max",
          "pFastest": 0.43,
          "predictedDeltaMs": -12.4,
          "sigma": 0.032
        },
        {
          "driverNumber": "4",
          "driverId": "norris-lando",
          "pFastest": 0.31,
          "predictedDeltaMs": -8.1,
          "sigma": 0.032
        }
      ]
    },
    "s2": {
      "drivers": [
        {
          "driverNumber": "4",
          "driverId": "norris-lando",
          "pFastest": 0.38,
          "predictedDeltaMs": -10.2,
          "sigma": 0.029
        },
        {
          "driverNumber": "1",
          "driverId": "verstappen-max",
          "pFastest": 0.36,
          "predictedDeltaMs": -9.8,
          "sigma": 0.029
        }
      ]
    },
    "s3": {
      "drivers": [
        {
          "driverNumber": "1",
          "driverId": "verstappen-max",
          "pFastest": 0.49,
          "predictedDeltaMs": -14.1,
          "sigma": 0.034
        },
        {
          "driverNumber": "4",
          "driverId": "norris-lando",
          "pFastest": 0.29,
          "predictedDeltaMs": -8.3,
          "sigma": 0.034
        }
      ]
    }
  },
  "drivers": [
    {
      "driverNumber": "1",
      "driverId": "verstappen-max",
      "sector1DeltaMs": -12.4,
      "sector2DeltaMs": -9.8,
      "sector3DeltaMs": -14.1
    },
    {
      "driverNumber": "4",
      "driverId": "norris-lando",
      "sector1DeltaMs": -8.1,
      "sector2DeltaMs": -10.2,
      "sector3DeltaMs": -8.3
    }
  ]
}

analytics.sector-paceSector Pace Analyticsanalytics

On sector anomaly · Race, Sprint

Per-sector pace deltas with anomaly detection; fires when a sector-pace anomaly is detected.

Backed by: sector pace analyzer. How the models work →

analytics.battleStrategy Battle Alertanalytics

On battle state change · Race, Sprint

On-track battle status between a driver and the car directly ahead (closing, holding, defending).

Backed by: strategy battle tracker. How the models work →

analytics.pit-windowPit Window Alertanalytics

On window open/urgent · Race, Sprint

Pit-window status (OPEN / URGENT) combining pit probability, undercut viability, tyre cliff risk, and gap context.

Backed by: pit window alert, pit_stop_tele_bilstm, EKF tire health. How the models work →

analytics.track-conditionsTrack Conditions Analyticsanalytics

Per lap · Race, Sprint

Track evolution and grip-condition analytics derived from field pace trends.

Backed by: track conditions model. How the models work →

analytics.pit-qualityPit Quality Alertanalytics

On pit completion · Race, Sprint

Pit-stop execution quality assessment (stationary time vs. expected) after a stop completes.

Backed by: pit quality model. How the models work →

TelemetryResults & Standings