Feed Catalog

Race Events

RaceHooks-computed synthetic event streams. Instead of receiving raw position arrays and computing events yourself, you subscribe once and receive pre-detected, structured events. This family has three feeds: raceevent (40+ event types — overtakes, pit stops, safety cars, fastest laps, retirements, and more), sessiontiming (aggregated session state), and qualifyingevent (qualifying-scoped events). Currently available for F1; equivalent feeds for other sports will be documented here as they launch.

Feed ID
raceevent
live
Cadence: event-driven · available on Live tier and above

Subscribe

bash
curl -X POST https://api.racehooks.io/v1/webhooks \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://your-app.com/race-events",
    "feedId": "raceevent"
  }'
subscribe.ts
import { RaceHooks } from "racehooks";

const rh = new RaceHooks({
  clientId:     process.env.RACEHOOKS_CLIENT_ID!,
  clientSecret: process.env.RACEHOOKS_CLIENT_SECRET!,
});

// All race events for the entire field
const { webhook, webhookSecret } = await rh.webhooks.create({
  feedId:     "raceevent",
  webhookUrl: "https://your-app.com/race-events",
});

// Overtakes and pit stops for your fantasy team only
await rh.webhooks.create({
  feedId:     "raceevent",
  webhookUrl: "https://scoring.myapp.com/hook",
  filters: { drivers: ["VER", "NOR", "LEC"] },
});

Payload structure

Every raceevent delivery shares a common envelope with an event-specific data object:

FieldTypeDescription
feedstringAlways "raceevent" — identifies this as a race event payload.
sessionIdstringUnique identifier for the current F1 session.
eventstringEvent type — one of the event types listed below.
lapnumberCurrent race lap number when the event fired.
utcstringISO 8601 timestamp of when the event was detected.
dataobjectEvent-specific data. Schema varies per event type.

Event types

session.startAll

Session status transitions to Started.

json
// data field
{
  "sessionType": "Race",
  "sessionName": "2026 Monaco Grand Prix — Race",
  "totalLaps": 78
}
session.completeRace / Sprint

Race or Sprint session result is finalised — winner confirmed.

json
// data field
{
  "sessionType": "Race",
  "sessionName": "2026 Monaco Grand Prix — Race",
  "winner": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  }
}
overtakeRace / Sprint

A driver gains a position on-track (not via pit strategy), detected from live timing position changes.

json
// data field
{
  "overtakingDriver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team",
    "newPosition": 1,
    "prevPosition": 2
  },
  "overtakenDriver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing",
    "newPosition": 2,
    "prevPosition": 1
  }
}
overtake.countRace / Sprint

Official cumulative overtake count for a driver increases (from overtakecounts feed).

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "cumulativeOvertakes": 7
}
overtake.attempt.startedRace / Sprint

A driver enters an active DRS overtake attempt window (OvertakeState = 2).

json
// data field
{
  "attackingDriver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "defendingDriver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "gapSeconds": 0.38
}
overtake.attempt.resolvedRace / Sprint

An active overtake attempt window closes (OvertakeState drops below 2).

json
// data field
{
  "attackingDriver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "defendingDriver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  }
}
lead.changeRace / Sprint

The race leader changes.

json
// data field
{
  "newLeader": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "previousLeader": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  }
}
battle.proximityRace / Sprint

A driver closes within DRS range of the car ahead (gap ≤ 1.0 s).

json
// data field
{
  "attackingDriver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "defendingDriver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "gapSeconds": 0.38,
  "closingRateSecPerLap": 0.12,
  "drsEnabled": true
}
positions.gainedRace / Sprint

A driver gains one or more positions (non-pit, detected from timing).

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "gridPosition": 4,
  "currentPosition": 2,
  "positionsGained": 2
}
positions.lostRace / Sprint

A driver loses one or more positions (non-pit, detected from timing).

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "gridPosition": 1,
  "currentPosition": 3,
  "positionsGained": -2
}
pit.entryAll

Driver enters the pit lane.

json
// data field
{
  "driver": {
    "driverId": "leclerc-charles",
    "constructorId": "ferrari",
    "number": "16",
    "tla": "LEC",
    "name": "Charles Leclerc",
    "team": "Scuderia Ferrari"
  },
  "compound": "MEDIUM",
  "tyreAge": 22
}
pit.exitAll

Driver exits the pit lane after a stop.

json
// data field
{
  "driver": {
    "driverId": "leclerc-charles",
    "constructorId": "ferrari",
    "number": "16",
    "tla": "LEC",
    "name": "Charles Leclerc",
    "team": "Scuderia Ferrari"
  },
  "stopNumber": 2,
  "positionAfterPit": 5
}
pit.stop.completeAll

Official pit stop timing confirmed (from PitStop feed during live sessions).

json
// data field
{
  "driver": {
    "driverId": "leclerc-charles",
    "constructorId": "ferrari",
    "number": "16",
    "tla": "LEC",
    "name": "Charles Leclerc",
    "team": "Scuderia Ferrari"
  },
  "lap": 28,
  "stopNumber": 2,
  "pitStopTimeMs": 2840,
  "pitLaneTimeMs": 19470
}
pit.fastestRace / Sprint

A driver sets the fastest pit lane time of the session.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "pitLaneTimeSec": 18.72,
  "previousBest": {
    "driver": {
      "driverId": "norris-lando",
      "constructorId": "mclaren",
      "number": "4",
      "tla": "NOR",
      "name": "Lando Norris",
      "team": "McLaren F1 Team"
    },
    "timeSec": 19.41
  }
}
fastest.lapAll

A new session fastest lap is set.

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "lapTime": {
    "display": "1:27.412",
    "ms": 87412
  },
  "previousBest": {
    "driver": {
      "driverId": "verstappen-max",
      "constructorId": "red-bull-racing",
      "number": "1",
      "tla": "VER",
      "name": "Max Verstappen",
      "team": "Red Bull Racing"
    },
    "lapTime": {
      "display": "1:28.103",
      "ms": 88103
    }
  }
}
fastest.lap.statsAll

Detailed breakdown of the current fastest lap holder's sectors and speed trap times.

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "lap": 51,
  "lapTime": {
    "display": "1:27.412",
    "ms": 87412
  },
  "sectors": [
    {
      "position": 1,
      "time": "28.441"
    },
    {
      "position": 1,
      "time": "31.204"
    },
    {
      "position": 1,
      "time": "27.767"
    }
  ],
  "speeds": {
    "i1": {
      "position": 1,
      "speedKmh": 312.4
    },
    "i2": {
      "position": 2,
      "speedKmh": 287.1
    },
    "fl": {
      "position": 1,
      "speedKmh": 302.7
    },
    "st": {
      "position": 1,
      "speedKmh": 347.2
    }
  }
}
retirementAll

A driver retires from the session.

json
// data field
{
  "driver": {
    "driverId": "leclerc-charles",
    "constructorId": "ferrari",
    "number": "16",
    "tla": "LEC",
    "name": "Charles Leclerc",
    "team": "Scuderia Ferrari"
  },
  "positionAtRetirement": 8,
  "pitsCompleted": 1
}
strategy.signalRace / Sprint

A potential undercut or overcut window is detected from team radio + timing data.

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "signals": [
    "undercut_window"
  ],
  "radioEventsLast3Min": 2,
  "currentPosition": 2,
  "compound": "MEDIUM",
  "tyreAge": 22
}
speedtrap.updateAll

A driver sets a new personal or session fastest speed at a speed trap.

json
// data field
{
  "zoneId": "ST",
  "zoneLabel": "Speed Trap",
  "rankings": [
    {
      "rank": 1,
      "driver": {
        "driverId": "verstappen-max",
        "constructorId": "red-bull-racing",
        "number": "1",
        "tla": "VER",
        "name": "Max Verstappen",
        "team": "Red Bull Racing"
      },
      "speedKmh": 347.2
    },
    {
      "rank": 2,
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "speedKmh": 344.8
    },
    {
      "rank": 3,
      "driver": {
        "driverId": "leclerc-charles",
        "constructorId": "ferrari",
        "number": "16",
        "tla": "LEC",
        "name": "Charles Leclerc",
        "team": "Scuderia Ferrari"
      },
      "speedKmh": 343.1
    }
  ]
}
safety.car.deployedAll

Safety Car or Virtual Safety Car deployed — type is "full" (SC) or "virtual" (VSC).

json
// data field
{
  "type": "full",
  "leader": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "message": "SAFETY CAR DEPLOYED"
}
safety.car.clearedAll

Safety Car has returned to pit lane and track is green.

json
// data field
{
  "type": "full",
  "leader": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  }
}
red.flagAll

Red flag shown — session suspended.

json
// data field
{
  "message": "RED FLAG"
}
session.clock.pausedAll

Session clock stops counting down (e.g. red flag, pre-start).

json
// data field
{
  "remaining": "0:42:11",
  "utc": "2026-06-08T14:22:18.441Z"
}
session.clock.resumedAll

Session clock resumes counting down after a pause.

json
// data field
{
  "remaining": "0:42:11",
  "utc": "2026-06-08T14:28:05.112Z"
}
qualifying.hot_lap.startedQualifying / Sprint Shoot-out

A driver begins a timed flying lap in qualifying.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "segment": "Q3"
}
qualifying.hot_lap.abortedQualifying / Sprint Shoot-out

A driver abandons their flying lap (slows, pits, yellow flag).

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "segment": "Q3"
}
qualifying.lap_improvementQualifying / Sprint Shoot-out

A driver sets a new personal best in the current qualifying segment.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "lapTime": {
    "display": "1:09.872",
    "ms": 69872
  },
  "improvementMs": -342,
  "position": 1,
  "segment": "Q3",
  "lap": 6
}
qualifying.driver_eliminatedQualifying

A driver is knocked out at the end of Q1 or Q2.

json
// data field
{
  "driver": {
    "driverId": "hamilton-lewis",
    "constructorId": "ferrari",
    "number": "44",
    "tla": "HAM",
    "name": "Lewis Hamilton",
    "team": "Scuderia Ferrari"
  },
  "position": 16,
  "lapTime": {
    "display": "1:11.204",
    "ms": 71204
  },
  "segment": "Q1",
  "finalPosition": 16
}
qualifying.pole_positionQualifying

Q3 ends — pole position confirmed.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "lapTime": {
    "display": "1:09.530",
    "ms": 69530
  },
  "marginToP2Ms": 241
}
qualifying.front_rowQualifying

Q3 ends — top 3 starting positions confirmed.

json
// data field
{
  "results": [
    {
      "driver": {
        "driverId": "verstappen-max",
        "constructorId": "red-bull-racing",
        "number": "1",
        "tla": "VER",
        "name": "Max Verstappen",
        "team": "Red Bull Racing"
      },
      "position": 1,
      "lapTime": {
        "display": "1:09.530",
        "ms": 69530
      }
    },
    {
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "position": 2,
      "lapTime": {
        "display": "1:09.771",
        "ms": 69771
      }
    },
    {
      "driver": {
        "driverId": "leclerc-charles",
        "constructorId": "ferrari",
        "number": "16",
        "tla": "LEC",
        "name": "Charles Leclerc",
        "team": "Scuderia Ferrari"
      },
      "position": 3,
      "lapTime": {
        "display": "1:09.983",
        "ms": 69983
      }
    }
  ]
}
qualifying.session_completeQualifying / Sprint Shoot-out

Full qualifying order confirmed at session end.

json
// data field
{
  "results": [
    {
      "driver": {
        "driverId": "verstappen-max",
        "constructorId": "red-bull-racing",
        "number": "1",
        "tla": "VER",
        "name": "Max Verstappen",
        "team": "Red Bull Racing"
      },
      "lapTime": {
        "display": "1:09.530",
        "ms": 69530
      },
      "position": 1
    },
    {
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "lapTime": {
        "display": "1:09.771",
        "ms": 69771
      },
      "position": 2
    },
    {
      "driver": {
        "driverId": "leclerc-charles",
        "constructorId": "ferrari",
        "number": "16",
        "tla": "LEC",
        "name": "Charles Leclerc",
        "team": "Scuderia Ferrari"
      },
      "lapTime": {
        "display": "1:09.983",
        "ms": 69983
      },
      "position": 3
    }
  ]
}
top.three.updateAll

The live top-3 leaderboard changes (position, gap, or fastest status).

json
// data field
{
  "drivers": [
    {
      "position": 1,
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "lapTime": "1:27.412",
      "gapToLeader": "",
      "overallFastest": true
    },
    {
      "position": 2,
      "driver": {
        "driverId": "verstappen-max",
        "constructorId": "red-bull-racing",
        "number": "1",
        "tla": "VER",
        "name": "Max Verstappen",
        "team": "Red Bull Racing"
      },
      "lapTime": "1:27.831",
      "gapToLeader": "+4.819",
      "overallFastest": false
    },
    {
      "position": 3,
      "driver": {
        "driverId": "leclerc-charles",
        "constructorId": "ferrari",
        "number": "16",
        "tla": "LEC",
        "name": "Charles Leclerc",
        "team": "Scuderia Ferrari"
      },
      "lapTime": "1:28.209",
      "gapToLeader": "+8.211",
      "overallFastest": false
    }
  ]
}
championship.prediction.updateRace / Sprint

Predicted championship standings change based on current race positions.

json
// data field
{
  "leadersChanged": false,
  "drivers": [
    {
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "currentPoints": 148,
      "projectedPoints": 173,
      "currentPosition": 1,
      "projectedPosition": 1,
      "delta": 25
    },
    {
      "driver": {
        "driverId": "verstappen-max",
        "constructorId": "red-bull-racing",
        "number": "1",
        "tla": "VER",
        "name": "Max Verstappen",
        "team": "Red Bull Racing"
      },
      "currentPoints": 136,
      "projectedPoints": 154,
      "currentPosition": 2,
      "projectedPosition": 2,
      "delta": 18
    }
  ]
}
standings.readyRace / Sprint

Unofficial race results are available — derived from live lap timing data immediately after session end. official: false.

json
// data field
{
  "raceId": "2026-monaco-r7",
  "raceName": "2026 Monaco Grand Prix",
  "resultCount": 20,
  "official": false
}
standings.updatedRace / Sprint

Official race results have been confirmed and written — sourced from the Wikipedia post-race scrape. official: true. Replaces any prior unofficial standings.

json
// data field
{
  "raceId": "2026-monaco-r7",
  "raceName": "2026 Monaco Grand Prix",
  "resultCount": 20,
  "official": true
}
investigation.openedAll

An FIA stewards investigation is opened against one or more drivers (UNDER INVESTIGATION or WILL BE INVESTIGATED race control message).

json
// data field
{
  "cars": [
    {
      "driverId": "norris-lando",
      "constructorId": "mclaren",
      "number": "4",
      "tla": "NOR",
      "name": "Lando Norris",
      "team": "McLaren F1 Team"
    },
    {
      "driverId": "russell-george",
      "constructorId": "mercedes",
      "number": "63",
      "tla": "RUS",
      "name": "George Russell",
      "team": "Mercedes-AMG Petronas F1 Team"
    }
  ],
  "deferred": false,
  "rawMessage": "CAR 4 (NOR) AND CAR 63 (RUS) - UNDER INVESTIGATION AFTER THE RACE"
}
penalty.appliedAll

A time, drive-through, or stop-and-go penalty is issued to a driver by the stewards.

json
// data field
{
  "driver": {
    "driverId": "russell-george",
    "constructorId": "mercedes",
    "number": "63",
    "tla": "RUS",
    "name": "George Russell",
    "team": "Mercedes-AMG Petronas F1 Team"
  },
  "penaltyType": "time",
  "seconds": 5,
  "reason": "LEAVING THE TRACK AND GAINING A LASTING ADVANTAGE",
  "rawMessage": "FIA STEWARDS: 5 SECOND TIME PENALTY FOR CAR 63 (RUS) - LEAVING THE TRACK AND GAINING A LASTING ADVANTAGE"
}
penalty.servedAll

A previously issued penalty has been served by the driver.

json
// data field
{
  "driver": {
    "driverId": "russell-george",
    "constructorId": "mercedes",
    "number": "63",
    "tla": "RUS",
    "name": "George Russell",
    "team": "Mercedes-AMG Petronas F1 Team"
  },
  "penaltyType": "time",
  "seconds": 5,
  "reason": null,
  "rawMessage": "FIA STEWARDS: PENALTY SERVED - 5 SECOND TIME PENALTY FOR CAR 63 (RUS)"
}
lap.time.deletedAll

A lap time is deleted by the stewards for a track limits violation.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "lapTime": "1:08.931",
  "turn": 12,
  "lapNumber": 17,
  "isPitLap": false,
  "rawMessage": "CAR 1 (VER) TIME 1:08.931 DELETED - TRACK LIMITS AT TURN 12 LAP 17"
}
overtake.enabledRace / Sprint

The overtake system (DRS / Overtake Mode) is enabled for the field.

json
// data field
{
  "enabled": true
}
overtake.disabledRace / Sprint

The overtake system (DRS / Overtake Mode) is disabled for the field (safety car, red flag, etc.).

json
// data field
{
  "enabled": false
}
team.double.stopRace / Sprint

Both drivers from the same constructor pit on the same lap (stacked or simultaneous stops).

json
// data field
{
  "constructor": {
    "constructorId": "mclaren",
    "name": "McLaren F1 Team"
  },
  "drivers": [
    {
      "driver": {
        "driverId": "norris-lando",
        "constructorId": "mclaren",
        "number": "4",
        "tla": "NOR",
        "name": "Lando Norris",
        "team": "McLaren F1 Team"
      },
      "stopNumber": 1
    },
    {
      "driver": {
        "driverId": "hamilton-lewis",
        "constructorId": "ferrari",
        "number": "44",
        "tla": "HAM",
        "name": "Lewis Hamilton",
        "team": "Scuderia Ferrari"
      },
      "stopNumber": 1
    }
  ],
  "lap": 28
}
strategy.crossoverRace / Sprint

An undercut or overcut outcome is confirmed — the pitting driver either emerged ahead (undercut) or behind (overcut) the car they were following before their stop.

json
// data field
{
  "type": "undercut",
  "pittedDriver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "carGained": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "lapsBetweenStops": 1,
  "gapAtCrossoverSec": 1.4
}
battle.train.formedRace / Sprint

3 or more cars are each within 1.0s of the car ahead, sustained for 2+ consecutive laps.

json
// data field
{
  "cars": [
    {
      "driverId": "norris-lando",
      "constructorId": "mclaren",
      "number": "4",
      "tla": "NOR",
      "name": "Lando Norris",
      "team": "McLaren F1 Team"
    },
    {
      "driverId": "verstappen-max",
      "constructorId": "red-bull-racing",
      "number": "1",
      "tla": "VER",
      "name": "Max Verstappen",
      "team": "Red Bull Racing"
    },
    {
      "driverId": "leclerc-charles",
      "constructorId": "ferrari",
      "number": "16",
      "tla": "LEC",
      "name": "Charles Leclerc",
      "team": "Scuderia Ferrari"
    }
  ],
  "gapChain": [
    0.38,
    0.61
  ],
  "lapsSustained": 3,
  "leadCar": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  }
}
session.restart.scheduledAll

An official restart time is announced via race control after a red flag suspension.

json
// data field
{
  "resumeAt": "14:30",
  "resumeAtUtc": "2026-06-08T14:30:00.000Z",
  "message": "RED FLAG - RACE RESTART EXPECTED AT 14:30"
}
red.flag.clearingAll

The session is suspended under a red flag (intermediate state between red.flag and session.clock.resumed).

json
// data field
{
  "message": "RACE SUSPENDED"
}
qualifying.segment.startQualifying / Sprint Shoot-out

A qualifying segment (Q1, Q2, or Q3) officially begins.

json
// data field
{
  "segment": "Q2",
  "part": 2,
  "utc": "2026-06-07T14:22:00.000Z"
}
qualifying.segment.endQualifying / Sprint Shoot-out

A qualifying segment ends — drivers' times in that segment are now final.

json
// data field
{
  "segment": "Q1",
  "part": 1,
  "utc": "2026-06-07T14:18:00.000Z"
}
lapseries.position.gainedRace / Sprint

Official end-of-lap position gain confirmed from laphistory data.

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "lap": 42,
  "newPosition": 1,
  "prevPosition": 2,
  "positionsGained": 1
}
lapseries.position.lostRace / Sprint

Official end-of-lap position loss confirmed from laphistory data.

json
// data field
{
  "driver": {
    "driverId": "verstappen-max",
    "constructorId": "red-bull-racing",
    "number": "1",
    "tla": "VER",
    "name": "Max Verstappen",
    "team": "Red Bull Racing"
  },
  "lap": 42,
  "newPosition": 2,
  "prevPosition": 1,
  "positionsGained": 1
}
driver.score.updateRace / Sprint

F1-provided driving style scores update for a driver (Brake, Throttle, Steering, etc.).

json
// data field
{
  "driver": {
    "driverId": "norris-lando",
    "constructorId": "mclaren",
    "number": "4",
    "tla": "NOR",
    "name": "Lando Norris",
    "team": "McLaren F1 Team"
  },
  "currentPosition": 1,
  "scores": {
    "Brake": 8.2,
    "Gforce Lat": 9.1,
    "Gforce Long": 7.4,
    "Steering": 8.8,
    "Throttle": 9.4,
    "Average": 8.6
  }
}

Handle deliveries

race-events-handler.ts
// Express endpoint
app.post("/race-events", express.raw({ type: "application/json" }), (req, res) => {
  const payload = JSON.parse(req.body.toString());

  switch (payload.event) {
    case "overtake":
      console.log(
        `${payload.data.overtakingDriver.tla} (P${payload.data.overtakingDriver.newPosition}) overtook ${payload.data.overtakenDriver.tla}`
      );
      break;
    case "pit.entry":
      console.log(`${payload.data.driver.tla} into the pits on lap ${payload.lap}`);
      break;
    case "fastest.lap":
      console.log(`Fastest lap: ${payload.data.driver.tla} ${payload.data.lapTime.display}`);
      break;
    case "safety.car.deployed":
      console.log(`${payload.data.type} deployed — leader: ${payload.data.leader.tla}`);
      break;
    case "retirement":
      console.log(`${payload.data.driver.tla} has retired after ${payload.data.pitsCompleted} stops`);
      break;
    case "qualifying.pole_position":
      console.log(
        `POLE: ${payload.data.driver.tla} — ${payload.data.lapTime.display} (+${(payload.data.marginToP2Ms / 1000).toFixed(3)}s to P2)`
      );
      break;
  }
  res.sendStatus(200);
});

Filtering race events

Use filters.drivers to scope race events to specific drivers. This is especially useful for fantasy scoring engines or fan apps that only care about a specific team or driver combination.

Position filters (positions.min / positions.max) are not applied to raceevent deliveries, since events like safety.car.deployed are session-wide and have no single position to filter on.

sessiontiming — aggregated session state live

sessiontiming aggregates TrackStatus, ExtrapolatedClock, LapCount, SessionData, and RaceControlMessages into a single coherent snapshot, delivered on every state change — so you have an up-to-date picture of the session without subscribing to multiple raw feeds. Every delivery is a full snapshot, not a diff.

json
{
  "feed": "sessiontiming",
  "sessionId": "9560",
  "utc": "2026-06-08T14:32:18.441Z",
  "state": "active",
  "flag": "GREEN",
  "lap": 42,
  "totalLaps": 78,
  "sessionType": "Race",
  "clock": {
    "remaining": "0:38:14",
    "extrapolating": true,
    "utc": "2026-06-08T14:32:18.441Z"
  },
  "resumeAt": null,
  "resumeAtUtc": null,
  "qualifyingSegment": null
}

Fields

FieldTypeDescription
statestringDerived session state — see the state values below.
flagstring"green" | "yellow" | "sc" | "vsc" | "red" | "checkered". Current track flag.
lapnumberCurrent race lap number. 0 during the formation lap.
totalLapsnumberTotal scheduled laps. 0 for timed sessions (practice, qualifying).
sessionTypestring"Race" | "Sprint" | "Qualifying" | "Practice1" | "Practice2" | "Practice3".
clockobject | nullSession clock: remaining time, extrapolating boolean, F1 server UTC. null before session start.
clock.remainingstringRemaining session time in "H:MM:SS" format.
clock.extrapolatingbooleantrue when F1 is extrapolating the clock (paused periods, formation lap) — the value is an estimate.
resumeAtstring | nullLocal time ("HH:MM") of an announced restart after a red flag. null otherwise.
qualifyingSegmentnumber | null1, 2, or 3 for the active qualifying segment (Q1/Q2/Q3). null outside qualifying.

State values

The state field is derived from the track status code, session started/finished flags, lap number, and qualifying segment. It is the recommended field for branching your integration logic.

StateDescription
pre_sessionBefore the session has officially started.
formation_lapRace/Sprint only — after session.start, before lap 1 begins.
racingGreen flag, lap ≥ 1.
yellow_flagTrackStatus code 2 — yellow flag sector.
safety_carTrackStatus code 4 — Safety Car deployed.
sc_endingTrackStatus code 7 — Safety Car returning this lap.
virtual_safety_carTrackStatus code 6 — Virtual Safety Car.
red_flagTrackStatus code 5 — session suspended.
qualifying_q1Q1 segment active.
qualifying_q2Q2 segment active.
qualifying_q3Q3 segment active.
pausedSession suspended but not red-flagged (e.g. practice delay).
finishedSession ended.

qualifyingevent — qualifying-scoped events live

qualifyingevent delivers the qualifying-specific synthetic events — lap improvements, eliminations, pole position, front row, and session complete — as their own subscribable stream scoped to Qualifying and Sprint Shoot-out sessions. The same events also appear inline on raceevent (the qualifying.* types above); subscribe to qualifyingevent when you want only the qualifying stream.

← Race ControlWeather →