Skip to content

Latest commit

 

History

History
544 lines (427 loc) · 11.9 KB

File metadata and controls

544 lines (427 loc) · 11.9 KB

OpenF1 API Integration Guide

Overview

This document provides detailed information about integrating with the OpenF1 API, including endpoints, data structures, filtering, and best practices.

Base Configuration

API Base URL

https://api.openf1.org/v1

Authentication

  • Historical Data: No authentication required (free)
  • Real-time Data: Requires paid account (not implemented yet)

Rate Limits

  • No explicit rate limits documented
  • Implement client-side caching to minimize requests
  • Use React Query for automatic request deduplication

Timeout

  • Query timeout: 10 seconds
  • Break large queries into smaller chunks if needed

Endpoints

1. Sessions

Purpose: List available race sessions

Endpoint: GET /v1/sessions

Sample Request:

GET https://api.openf1.org/v1/sessions?year=2024&session_name=Race

Query Parameters:

Parameter Type Description Example
session_key number Unique session identifier 9161
session_name string Session type Race, Qualifying, Practice 1
year number Season year 2024
circuit_short_name string Circuit abbreviation Monaco, Silverstone
date_start string Start date filter 2024-05-26

Response Structure:

interface Session {
  session_key: number
  session_name: string
  date_start: string  // ISO 8601
  date_end: string    // ISO 8601
  gmt_offset: string
  session_type: string
  meeting_key: number
  location: string
  country_name: string
  circuit_key: number
  circuit_short_name: string
  year: number
}

Example Response:

[
  {
    "session_key": 9161,
    "session_name": "Race",
    "date_start": "2023-09-16T13:00:00",
    "date_end": "2023-09-16T15:00:00",
    "gmt_offset": "+02:00",
    "session_type": "Race",
    "meeting_key": 1217,
    "location": "Singapore",
    "country_name": "Singapore",
    "circuit_key": 61,
    "circuit_short_name": "Singapore",
    "year": 2023
  }
]

2. Location

Purpose: GPS coordinates of cars on track

Endpoint: GET /v1/location

Sample Request:

GET https://api.openf1.org/v1/location?session_key=9161&driver_number=1&date>2023-09-16T13:00:00

Query Parameters:

Parameter Type Description Example
session_key number Session identifier 9161
driver_number number Driver number 1, 44, 16
date string Timestamp filter 2023-09-16T13:00:00
date> string After timestamp 2023-09-16T13:00:00
date< string Before timestamp 2023-09-16T14:00:00

Response Structure:

interface LocationData {
  date: string           // ISO 8601 timestamp
  driver_number: number  // Driver number
  meeting_key: number
  session_key: number
  x: number             // Track coordinate X
  y: number             // Track coordinate Y
  z: number             // Track coordinate Z (elevation)
  lat: number           // Latitude
  lng: number           // Longitude
}

Usage Notes:

  • Use date> and date< for time range queries
  • Coordinates update approximately every 0.1 seconds
  • Use x, y, z for track-relative positioning
  • Use lat, lng for GPS mapping

3. Position

Purpose: Race position of drivers

Endpoint: GET /v1/position

Sample Request:

GET https://api.openf1.org/v1/position?session_key=9161&date>2023-09-16T13:00:00

Query Parameters:

Parameter Type Description Example
session_key number Session identifier 9161
driver_number number Driver number 1
position number Race position 1, 2, 3
position<= number Position less than or equal 3
date string Timestamp filter 2023-09-16T13:00:00

Response Structure:

interface PositionData {
  date: string
  driver_number: number
  meeting_key: number
  session_key: number
  position: number
}

4. Laps

Purpose: Lap times and lap numbers

Endpoint: GET /v1/laps

Sample Request:

GET https://api.openf1.org/v1/laps?session_key=9161&driver_number=1

Query Parameters:

Parameter Type Description Example
session_key number Session identifier 9161
driver_number number Driver number 1
lap_number number Specific lap 10

Response Structure:

interface LapData {
  date_start: string
  driver_number: number
  duration_sector_1: number  // seconds
  duration_sector_2: number  // seconds
  duration_sector_3: number  // seconds
  i1_speed: number          // km/h
  i2_speed: number          // km/h
  is_pit_out_lap: boolean
  lap_duration: number      // seconds
  lap_number: number
  meeting_key: number
  session_key: number
  st_speed: number          // km/h (speed trap)
}

5. Intervals

Purpose: Time gaps between drivers

Endpoint: GET /v1/intervals

Sample Request:

GET https://api.openf1.org/v1/intervals?session_key=9161&driver_number=1

Response Structure:

interface IntervalData {
  date: string
  driver_number: number
  gap_to_leader: number     // seconds
  interval: number          // seconds to car ahead
  meeting_key: number
  session_key: number
}

6. Pit Stops

Purpose: Pit stop information

Endpoint: GET /v1/pit

Sample Request:

GET https://api.openf1.org/v1/pit?session_key=9161

Response Structure:

interface PitData {
  date: string
  driver_number: number
  lap_number: number
  pit_duration: number      // seconds
  meeting_key: number
  session_key: number
}

7. Car Data (Telemetry)

Purpose: Real-time car telemetry

Endpoint: GET /v1/car_data

Sample Request:

GET https://api.openf1.org/v1/car_data?session_key=9161&driver_number=1&date>2023-09-16T13:00:00

Response Structure:

interface CarData {
  brake: number            // 0-100 (percentage)
  date: string
  driver_number: number
  drs: number             // 0-14 (DRS status)
  meeting_key: number
  n_gear: number          // 1-8
  rpm: number             // Engine RPM
  session_key: number
  speed: number           // km/h
  throttle: number        // 0-100 (percentage)
}

DRS Values:

  • 0 = Off
  • 10-14 = Various DRS states (available, enabled, etc.)

8. Stints

Purpose: Tire strategy and stints

Endpoint: GET /v1/stints

Sample Request:

GET https://api.openf1.org/v1/stints?session_key=9161&driver_number=1

Response Structure:

interface StintData {
  compound: string         // "SOFT", "MEDIUM", "HARD", "INTERMEDIATE", "WET"
  driver_number: number
  lap_end: number
  lap_start: number
  meeting_key: number
  session_key: number
  stint_number: number
  tyre_age_at_start: number  // laps
}

Data Filtering

Time-Based Filtering

OpenF1 supports comparison operators for date filtering:

// After a specific time
date>2023-09-16T13:00:00

// Before a specific time
date<2023-09-16T14:00:00

// Between two times
date>2023-09-16T13:00:00&date<2023-09-16T14:00:00

// Exact time
date=2023-09-16T13:00:00

Numeric Filtering

// Position filtering
position<=3          // Top 3 positions
position=1           // Leader only
driver_number=44     // Specific driver

Latest Data

Use latest parameter to get most recent data point:

GET /v1/location?session_key=9161&driver_number=1&latest

Best Practices

1. Caching Strategy

// React Query configuration
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,  // 5 minutes
      cacheTime: 10 * 60 * 1000,  // 10 minutes
      refetchOnWindowFocus: false,
      retry: 1,
    },
  },
})

2. Batch Requests

Instead of:

// ❌ Bad - Multiple requests
const driver1 = await getLocation(sessionKey, 1)
const driver2 = await getLocation(sessionKey, 2)
const driver3 = await getLocation(sessionKey, 3)

Do:

// ✅ Good - Single request
const allDrivers = await getLocation(sessionKey)

3. Time Range Queries

// ✅ Good - Specific time range
const data = await getLocationData(sessionKey, {
  'date>': '2023-09-16T13:00:00',
  'date<': '2023-09-16T13:01:00',
})

4. Error Handling

try {
  const data = await getLocationData(sessionKey)
  return data
} catch (error) {
  if (axios.isAxiosError(error)) {
    if (error.response?.status === 404) {
      console.error('Session not found')
    } else if (error.response?.status === 500) {
      console.error('API server error')
    } else if (error.code === 'ECONNABORTED') {
      console.error('Request timeout')
    }
  }
  throw error
}

5. Pagination for Large Datasets

// For large time ranges, split into chunks
const startTime = new Date('2023-09-16T13:00:00')
const endTime = new Date('2023-09-16T15:00:00')
const chunkSize = 5 * 60 * 1000 // 5 minutes

const chunks = []
for (let time = startTime; time < endTime; time += chunkSize) {
  const chunkEnd = new Date(time.getTime() + chunkSize)
  chunks.push({
    start: time.toISOString(),
    end: chunkEnd.toISOString(),
  })
}

const allData = await Promise.all(
  chunks.map(chunk => 
    getLocationData(sessionKey, {
      'date>': chunk.start,
      'date<': chunk.end,
    })
  )
)

Service Implementation Example

// services/openf1/client.ts
import axios from 'axios'

export const apiClient = axios.create({
  baseURL: 'https://api.openf1.org/v1',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  },
})

// services/openf1/location.ts
import { apiClient } from './client'
import type { LocationData } from '@/types/openf1'

export const getLocationData = async (
  sessionKey: number,
  filters?: Record<string, string | number>
): Promise<LocationData[]> => {
  const response = await apiClient.get<LocationData[]>('/location', {
    params: {
      session_key: sessionKey,
      ...filters,
    },
  })
  return response.data
}

// Custom hook
import { useQuery } from '@tanstack/react-query'

export const useLocationData = (
  sessionKey: number | null,
  filters?: Record<string, string | number>
) => {
  return useQuery({
    queryKey: ['location', sessionKey, filters],
    queryFn: () => sessionKey ? getLocationData(sessionKey, filters) : null,
    enabled: !!sessionKey,
    refetchInterval: 1000, // Refetch every second for "live" updates
  })
}

Testing with Sample Data

Test Session Keys

Use these session keys for testing:

  • 9161 - Singapore GP 2023 Race
  • 9158 - Singapore GP 2023 Qualifying
  • 9165 - Japan GP 2023 Race

Sample API Calls

# Get session info
curl "https://api.openf1.org/v1/sessions?session_key=9161"

# Get location data for driver 1
curl "https://api.openf1.org/v1/location?session_key=9161&driver_number=1&date>2023-09-16T13:00:00&date<2023-09-16T13:01:00"

# Get race positions
curl "https://api.openf1.org/v1/position?session_key=9161"

# Get telemetry
curl "https://api.openf1.org/v1/car_data?session_key=9161&driver_number=1&date>2023-09-16T13:00:00&date<2023-09-16T13:01:00"

Common Issues & Solutions

Issue: Query Timeout

Solution: Break large queries into smaller time chunks

Issue: Too Much Data

Solution: Use time-based filtering and pagination

Issue: Missing Data Points

Solution: Handle null/undefined gracefully, interpolate if needed

Issue: Coordinate Conversion

Solution: Use provided x, y, z coordinates instead of lat, lng for track visualization


Resources