{"openapi":"3.2.0","info":{"title":"Formula 1 API","description":"Every Formula 1 season since 1950. Drivers, teams, circuits, results, lap-by-lap timing and standings, plus live race-weekend timing.","version":"1.0.0"},"servers":[{"url":"https://formula-1.jojapi.net"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"F1 Drivers"},{"name":"F1 Events"},{"name":"F1 Circuits"},{"name":"F1 Seasons"},{"name":"F1 Teams"},{"name":"Bulk Export"},{"name":"F1 Standings"},{"name":"F1 Race Control"},{"name":"F1 State"},{"name":"F1 Timing"},{"name":"F1 Weather"},{"name":"F1 Telemetry"}],"x-agent-commerce":{"catalog_url":"https://formula-1.jojapi.net/_jojapi/agent/plans","discovery_url":"https://formula-1.jojapi.net/.well-known/x402","directory_url":"https://agents.jojapi.net/apis/formula-1","docs":"https://docs.jojapi.com/consumers/agents"},"paths":{"/v1/formula1/drivers":{"get":{"operationId":"get_v1_formula1_drivers","summary":"List all Formula 1 drivers","description":"Retrieve a paginated list of all Formula 1 drivers. Returns basic driver information including name, number, TLA, birth date, and country. Supports pagination with a maximum limit of 50 drivers per page.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/drivers?page=1&limit=20\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Drivers"],"responses":{"200":{"description":"Successfully retrieved paginated list of drivers.","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"data":{"description":"The page of results. Item shape depends on the endpoint.","type":"array","items":{"type":"object"}},"meta":{"description":"Pagination details for this response.","allOf":[{"type":"object","properties":{"page":{"type":"number","description":"Current page (1-indexed).","example":1},"limit":{"type":"number","description":"Page size used for this response (max 50).","example":20},"total":{"type":"number","description":"Total number of items across all pages.","example":858},"totalPages":{"type":"number","description":"Total number of pages at this limit.","example":43}},"required":["page","limit","total","totalPages"]}]}},"required":["data","meta"]},{"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the driver.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"firstName":{"type":"string","nullable":true,"description":"Given name.","example":"Max"},"lastName":{"type":"string","nullable":true,"description":"Family name.","example":"Verstappen"},"birthDate":{"type":"string","nullable":true,"description":"Date of birth (YYYY-MM-DD), null when unknown.","example":"1997-09-30"},"number":{"type":"number","nullable":true,"description":"Current or last-used racing number, null when unknown.","example":1},"tla":{"type":"string","nullable":true,"description":"Three-letter abbreviation shown on timing screens, null for sports that do not use one.","example":"VER"},"country":{"type":"object","properties":{"name":{"type":"string"},"twoCode":{"type":"string"},"threeCode":{"type":"string"}},"required":["name","twoCode","threeCode"]}},"required":["id","firstName","lastName","birthDate","number","tla","country"]}}}}]}}}},"400":{"description":"Invalid query parameters — `page` or `limit` is not a positive integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","default":1}},{"name":"limit","in":"query","description":"Number of items per page (max: 50)","required":false,"schema":{"type":"integer","default":20}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/drivers/{id}":{"get":{"operationId":"get_v1_formula1_drivers_id","summary":"Get driver details by ID","description":"Retrieve detailed information about a specific Formula 1 driver by their unique ID. Returns comprehensive driver data including personal information, career statistics, team history, and championship results.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/drivers/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Drivers"],"responses":{"200":{"description":"Successfully retrieved driver details.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the driver.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"firstName":{"type":"string","description":"Given name.","example":"Max"},"lastName":{"type":"string","description":"Family name.","example":"Verstappen"},"nickName":{"type":"string","nullable":true,"description":"Nickname, null when none on record."},"number":{"type":"number","description":"Racing number.","example":1},"code":{"type":"string","nullable":true,"description":"Three-letter abbreviation, null for sports that do not use one.","example":"VER"},"birthDate":{"type":"string","nullable":true,"description":"Date of birth (YYYY-MM-DD), null when unknown.","example":"1997-09-30"},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}},"required":["name","twoCode","threeCode"]},"socials":{"description":"Social media profiles on record.","allOf":[{"type":"object","properties":{"twitter":{"type":"string","nullable":true,"description":"X/Twitter profile URL, null when not on record.","example":"https://x.com/Max33Verstappen"},"youtube":{"type":"string","nullable":true,"description":"YouTube channel URL, null when not on record."},"website":{"type":"string","nullable":true,"description":"Personal website URL, null when not on record.","example":"https://www.verstappen.com"},"bluesky":{"type":"string","nullable":true,"description":"Bluesky profile URL, null when not on record."},"twitch":{"type":"string","nullable":true,"description":"Twitch channel URL, null when not on record."},"instagram":{"type":"string","nullable":true,"description":"Instagram profile URL, null when not on record.","example":"https://www.instagram.com/maxverstappen1"},"facebook":{"type":"string","nullable":true,"description":"Facebook page URL, null when not on record."},"tiktok":{"type":"string","nullable":true,"description":"TikTok profile URL, null when not on record."}},"required":["twitter","youtube","website","bluesky","twitch","instagram","facebook","tiktok"]}]},"careerHistory":{"description":"Team stints across race and sprint entries, most recent first.","type":"array","items":{"type":"object","properties":{"teamId":{"type":"string","nullable":true,"description":"Identifier of the team, null for entries without a recorded team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"teamName":{"type":"string","nullable":true,"description":"Full team name at the time.","example":"Oracle Red Bull Racing"},"teamShortName":{"type":"string","nullable":true,"description":"Short team name.","example":"Red Bull"},"teamColor":{"type":"string","nullable":true,"description":"Team branding color as a hex string.","example":"#3671C6"},"startYear":{"type":"number","description":"First year of the stint.","example":2016},"endYear":{"type":"number","description":"Last year of the stint (current year for ongoing stints).","example":2025}},"required":["teamId","teamName","teamShortName","teamColor","startYear","endYear"]}}},"required":["id","firstName","lastName","nickName","number","code","birthDate","country","socials","careerHistory"]}}}},"400":{"description":"Invalid driver ID format — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Formula 1 driver not found — no driver exists with the given ID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the driver","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/events":{"get":{"operationId":"get_v1_formula1_events","summary":"List all Formula 1 events","description":"Retrieve a paginated list of all Formula 1 race events (Grand Prix). Returns event details including name, dates, status, location information, and session schedule. Supports pagination with a maximum limit of 50 events per page.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events?page=1&limit=20\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Events"],"responses":{"200":{"description":"Successfully retrieved paginated list of events.","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"data":{"description":"The page of results. Item shape depends on the endpoint.","type":"array","items":{"type":"object"}},"meta":{"description":"Pagination details for this response.","allOf":[{"type":"object","properties":{"page":{"type":"number","description":"Current page (1-indexed).","example":1},"limit":{"type":"number","description":"Page size used for this response (max 50).","example":20},"total":{"type":"number","description":"Total number of items across all pages.","example":858},"totalPages":{"type":"number","description":"Total number of pages at this limit.","example":43}},"required":["page","limit","total","totalPages"]}]}},"required":["data","meta"]},{"properties":{"data":{"type":"array","items":{"type":"object","properties":{"sportId":{"type":"string","description":"Sport the event belongs to.","example":"formula1"},"schedule":{"description":"Sessions that make up the event weekend, in chronological order.","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the session.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Session display name.","example":"Race"},"type":{"type":"string","description":"Session type: practice, qualifying, sprint, sprint_qualifying, race or other.","example":"race"},"status":{"type":"string","description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed"},"startTime":{"type":"string","nullable":true,"description":"Scheduled start (ISO 8601, UTC). Null when not yet scheduled.","example":"2025-05-25T13:00:00.000Z"},"endTime":{"type":"string","nullable":true,"description":"Scheduled end (ISO 8601, UTC). Null when not yet scheduled.\n\nSome feeds publish only a session start. For those series (MotoGP, Moto2,\nMoto3, NASCAR, and Formula E sessions with no published finish) this is an\nexpected end rather than a value the timing provider supplied: the\nscheduled length for the session type, or for a NASCAR race its scheduled\nlap count at that track's historical pace, which carries a median error\naround nine minutes. Treat it as the window the session is expected to\noccupy, not the instant the flag fell. `status` is the authoritative\nsignal for whether a session is still running.","example":"2025-05-25T15:00:00.000Z"}},"required":["id","name","type","status","startTime","endTime"]}},"id":{"type":"string","description":"Stable unique identifier of the event.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Official event name."},"dateStart":{"type":"string","nullable":true,"description":"First day of the event (YYYY-MM-DD).","example":"2025-05-23"},"dateEnd":{"type":"string","nullable":true,"description":"Last day of the event (YYYY-MM-DD).","example":"2025-05-25"},"status":{"type":"string","description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed"},"location":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"city":{"type":"string","nullable":true},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}}}},"required":["id","name","city","country"]}},"required":["sportId","schedule","id","name","dateStart","dateEnd","status","location"]}}}}]}}}},"400":{"description":"Invalid query parameters — `page`, `limit` or `year` is not a valid integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","default":1}},{"name":"limit","in":"query","description":"Number of items per page (max: 50)","required":false,"schema":{"type":"integer","default":20}},{"name":"year","in":"query","description":"Filter events to a single season (year).","required":false,"schema":{"type":"integer"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/events/{id}":{"get":{"operationId":"get_v1_formula1_events_id","summary":"Get event details by ID","description":"Retrieve detailed information about a specific Formula 1 event (Grand Prix) by its unique ID. Returns comprehensive event data including location details, dates, status, full session schedule, and navigation to previous/next events in the calendar.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Events"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"schedule":{"description":"Sessions that make up the event weekend, in chronological order.","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the session.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Session display name.","example":"Race"},"type":{"type":"string","description":"Session type: practice, qualifying, sprint, sprint_qualifying, race or other.","example":"race"},"status":{"type":"string","description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed"},"startTime":{"type":"string","nullable":true,"description":"Scheduled start (ISO 8601, UTC). Null when not yet scheduled.","example":"2025-05-25T13:00:00.000Z"},"endTime":{"type":"string","nullable":true,"description":"Scheduled end (ISO 8601, UTC). Null when not yet scheduled.\n\nSome feeds publish only a session start. For those series (MotoGP, Moto2,\nMoto3, NASCAR, and Formula E sessions with no published finish) this is an\nexpected end rather than a value the timing provider supplied: the\nscheduled length for the session type, or for a NASCAR race its scheduled\nlap count at that track's historical pace, which carries a median error\naround nine minutes. Treat it as the window the session is expected to\noccupy, not the instant the flag fell. `status` is the authoritative\nsignal for whether a session is still running.","example":"2025-05-25T15:00:00.000Z"}},"required":["id","name","type","status","startTime","endTime"]}},"id":{"type":"string","description":"Stable unique identifier of the event.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Official event name."},"dateStart":{"type":"string","nullable":true,"description":"First day of the event (YYYY-MM-DD).","example":"2025-05-23"},"dateEnd":{"type":"string","nullable":true,"description":"Last day of the event (YYYY-MM-DD).","example":"2025-05-25"},"status":{"type":"string","description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed"},"location":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"city":{"type":"string","nullable":true},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}}}},"required":["id","name","city","country"]},"sportId":{"type":"string","description":"Sport the event belongs to (database form, e.g. formula-1).","example":"formula-1"},"season":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"year":{"type":"number"}},"required":["id","name","year"]},"previousEventId":{"type":"string","nullable":true,"description":"Identifier of the previous event in the same season, null at the start of the calendar.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"nextEventId":{"type":"string","nullable":true,"description":"Identifier of the next event in the same season, null at the end of the calendar."}},"required":["schedule","id","name","dateStart","dateEnd","status","location","sportId","season","previousEventId","nextEventId"]}}}},"400":{"description":"Invalid event ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Event not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the event","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/events/{eventId}/sessions":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions","summary":"List all sessions for an event","description":"Retrieve a list of all sessions (Practice, Qualifying, Sprint, Race) for a specific Formula 1 event. Returns session details including name, type, start/end times, and status for each session in the event weekend.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/sessions\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Events"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the session.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Session display name.","example":"Race"},"eventId":{"type":"string","description":"Identifier of the parent event.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"startTime":{"format":"date-time","type":"string","nullable":true,"description":"Scheduled start (ISO 8601, UTC).","example":"2025-05-25T13:00:00.000Z"},"endTime":{"format":"date-time","type":"string","nullable":true,"description":"Scheduled end (ISO 8601, UTC).\n\nSome feeds publish only a session start. For those series (MotoGP, Moto2,\nMoto3, NASCAR, and Formula E sessions with no published finish) this is an\nexpected end rather than a value the timing provider supplied: the\nscheduled length for the session type, or for a NASCAR race its scheduled\nlap count at that track's historical pace, which carries a median error\naround nine minutes. Treat it as the window the session is expected to\noccupy, not the instant the flag fell. `status` is the authoritative\nsignal for whether a session is still running.","example":"2025-05-25T15:00:00.000Z"},"type":{"description":"Session type: practice, qualifying, sprint, sprint_qualifying, race or other.","example":"race","enum":["race","practice","qualifying","sprint","sprint_qualifying","testing","shakedown","special_stage","power_stage","other"],"type":"string"},"status":{"description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed","enum":["scheduled","ongoing","completed","cancelled","interrupted"],"type":"string"},"description":{"type":"string","description":"Human-readable description of the session."}},"required":["id","name","eventId","startTime","endTime","type","status","description"]}}}}},"400":{"description":"Invalid event ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Event not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"eventId","in":"path","description":"Unique identifier of the event","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId","summary":"Get session details by ID","description":"Retrieve detailed information about a specific session within a Formula 1 event. Returns comprehensive session data including timing information, status, and complete results with driver positions, times, gaps, and session-specific statistics.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/sessions/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Events"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the session.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Session display name.","example":"Race"},"eventId":{"type":"string","description":"Identifier of the parent event.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"startTime":{"format":"date-time","type":"string","nullable":true,"description":"Scheduled start (ISO 8601, UTC).","example":"2025-05-25T13:00:00.000Z"},"endTime":{"format":"date-time","type":"string","nullable":true,"description":"Scheduled end (ISO 8601, UTC).\n\nSome feeds publish only a session start. For those series (MotoGP, Moto2,\nMoto3, NASCAR, and Formula E sessions with no published finish) this is an\nexpected end rather than a value the timing provider supplied: the\nscheduled length for the session type, or for a NASCAR race its scheduled\nlap count at that track's historical pace, which carries a median error\naround nine minutes. Treat it as the window the session is expected to\noccupy, not the instant the flag fell. `status` is the authoritative\nsignal for whether a session is still running.","example":"2025-05-25T15:00:00.000Z"},"type":{"description":"Session type: practice, qualifying, sprint, sprint_qualifying, race or other.","example":"race","enum":["race","practice","qualifying","sprint","sprint_qualifying","testing","shakedown","special_stage","power_stage","other"],"type":"string"},"status":{"description":"Lifecycle status: scheduled, ongoing or completed.","example":"completed","enum":["scheduled","ongoing","completed","cancelled","interrupted"],"type":"string"},"description":{"type":"string","description":"Human-readable description of the session."},"weather":{"type":"object","properties":{"condition":{"type":"string","nullable":true},"temperature":{"type":"number","nullable":true},"humidity":{"type":"number","nullable":true},"windSpeed":{"type":"number","nullable":true}},"required":["condition","temperature","humidity","windSpeed"]},"results":{"description":"Full results table, classified order first.","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of this result row.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"string","description":"Finishing position as a string; non-numeric values such as NC, DNF or DSQ appear for unclassified entries.","example":"1"},"lapTime":{"type":"string","nullable":true,"description":"Best/representative lap time, null when not recorded.","example":"1:12.909"},"displayTime":{"type":"string","nullable":true,"description":"Display-formatted race time or gap as shown on the classification: the\nwinner's elapsed time, a time gap such as +0.308, or laps down such as\n+4 Laps.","example":"1:38:57.094"},"laps":{"type":"number","nullable":true,"description":"Laps completed, null when not recorded.","example":78},"driver":{"description":"Driver who set this result.","allOf":[{"type":"object","properties":{"id":{"type":"string","description":"Stable identifier for the driver across seasons and series.","example":"6f1c1d80-1f4e-4b0e-9a2c-0f1b6d4a8e21"},"firstName":{"type":"string","nullable":true,"example":"Lando"},"lastName":{"type":"string","nullable":true,"example":"Norris"},"code":{"type":"string","nullable":true,"description":"Three-letter abbreviation used on timing screens.","example":"NOR"},"number":{"type":"number","nullable":true,"description":"The number this driver carried in THIS session, not the one they carry\ntoday, so a historical result keeps the number of its own era: a 2025 F1\nresult gives Verstappen 1 and Norris 4 even though they now carry 3 and 1.\nIdentical to the row's `carNumber`, and the field to key on when matching\nagainst live timing. Null where the classification records no number,\nwhich is most F1 sessions before 2006.","example":4}},"required":["id","firstName","lastName","code","number"]}]},"carNumber":{"type":"string","nullable":true,"description":"Number on the car in this session, as recorded on the classification, and\nthe field to key on when matching against timing data. Same value as\ndriver.number, kept as a string because some series use numbers with\nleading zeros.","example":"87"},"team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"shortName":{"type":"string","nullable":true},"color":{"type":"string","nullable":true}},"required":["id","name","shortName","color"]},"chassis":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"}},"required":["id","name"]},"engineManufacturer":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"}},"required":["id","name"]},"fastestLap":{"type":"object","properties":{"rank":{"type":"number","nullable":true},"time":{"type":"string","nullable":true},"lap":{"type":"number","nullable":true}},"required":["rank","time","lap"]},"status":{"type":"string","nullable":true,"description":"Finishing status from the series' official classification. The vocabulary\nis per sport, so branch on it per sport:\n- F1: OK for a classified finish, else DNF, DNS or DSQ.\n- F2, F3, Formula E: null for a classified finish, else DNF, DNS or DSQ.\n- NASCAR (Cup, Xfinity, Truck): Running means the car was still running at\n  the checkered flag, on the lead lap or not, and is the value for nearly\n  every finisher. Anything else is NASCAR's retirement reason, e.g.\n  Accident, Engine, Suspension, Brakes, DVP, Too Slow.\n- IndyCar: Running, Contact, Mechanical, Retired, Off Course, DNS.\n- MotoGP, Moto2, Moto3: INSTND (classified), OUTSTND (retired),\n  NOTFINISHFIRST, NOTSTARTED, DISQUALIFIED, NOTONRESTARTGRID, OUTOFLAPS.\n- WEC: Classified, Retired, Not classified, Disqualified.\nLaps down and the gap to the winner are in displayTime, not here. Null\nwhen not recorded.","example":"Running"},"points":{"type":"number","description":"Championship points awarded for this result.","example":25},"gap":{"type":"string","nullable":true},"interval":{"type":"string","nullable":true,"description":"Interval to the car ahead, on the same basis as `gap`. Null for the\nleader and outside enriched F1 sessions.","example":"+1.271"},"pitStops":{"type":"number","nullable":true,"description":"Pit stops made, null outside enriched F1 sessions.","example":2},"bestLapTime":{"type":"string","nullable":true,"description":"Best lap time from live timing, null outside enriched F1 sessions.","example":"1:13.221"},"bestLapNumber":{"type":"number","nullable":true,"description":"Lap on which the best time was set, null outside enriched F1 sessions.","example":71},"sectors":{"type":"object","properties":{"s1":{"type":"string","nullable":true},"s2":{"type":"string","nullable":true},"s3":{"type":"string","nullable":true}},"required":["s1","s2","s3"]},"tireStrategy":{"type":"array","items":{"type":"object","properties":{"compound":{"type":"string"},"laps":{"type":"number"},"isNew":{"type":"boolean"}},"required":["compound","laps","isNew"]}},"gridPosition":{"type":"number","nullable":true},"q1Time":{"type":"string","nullable":true},"q2Time":{"type":"string","nullable":true,"description":"Q2 lap time for qualifying sessions, null otherwise.","example":"1:11.278"},"q3Time":{"type":"string","nullable":true,"description":"Q3 lap time for qualifying sessions, null otherwise.","example":"1:10.954"}},"required":["id","position","lapTime","displayTime","laps","driver","carNumber","team","chassis","engineManufacturer","fastestLap","status","points","gap","interval","pitStops","bestLapTime","bestLapNumber","sectors","tireStrategy","gridPosition","q1Time","q2Time","q3Time"]}}},"required":["id","name","eventId","startTime","endTime","type","status","description","weather","results"]}}}},"400":{"description":"Invalid event or session ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Event or session not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"eventId","in":"path","description":"Unique identifier of the event","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","description":"Unique identifier of the session","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}/lap-chart":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId_lap_chart","summary":"Get the lap chart for a session","description":"Position-by-lap running order (car number per cell). Defaults to JSON; use ?format=csv for a pivoted grid or ?format=txt for a printed lap chart.","tags":["F1 Events"],"responses":{"200":{"description":"Lap chart for the session (position × lap, car number per cell).","content":{"application/json":{"example":{"session":{"id":"b7a75618-06a3-4c36-a172-d05f08c7f62b","type":"race","event":"Austrian Grand Prix","totalLaps":72},"lapNumbers":[1,2,3],"rows":[{"position":1,"cars":["63","63","63"]},{"position":2,"cars":["44","44","3"]},{"position":3,"cars":["16","3","3"]}]}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No timing data for this session."}},"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}/lap-times":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId_lap_times","summary":"Get individual lap times for a session","description":"Per-driver lap times as a car×lap grid. Defaults to JSON; use ?format=csv or ?format=txt for a downloadable file.","tags":["F1 Events"],"responses":{"200":{"description":"Per-driver lap times for the session (car × lap grid).","content":{"application/json":{"example":{"session":{"id":"b7a75618-06a3-4c36-a172-d05f08c7f62b","type":"race","event":"Austrian Grand Prix","totalLaps":72},"lapNumbers":[3,4,5],"rows":[{"car":"63","driver":"RUS","times":["1:12.037","1:11.818","1:11.779"]},{"car":"1","driver":"NOR","times":["1:12.531","1:12.104","1:11.996"]}]}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No timing data for this session."}},"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}/results":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId_results","summary":"Get session results","description":"Retrieve just the results for a specific session within a Formula 1 event. Returns an array of driver results including positions, times, gaps, fastest laps, pit stops, and session-specific data (qualifying times for qualifying sessions, race classification for races, etc.).\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/sessions/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/results\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Events"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of this result row.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"string","description":"Finishing position as a string; non-numeric values such as NC, DNF or DSQ appear for unclassified entries.","example":"1"},"lapTime":{"type":"string","nullable":true,"description":"Best/representative lap time, null when not recorded.","example":"1:12.909"},"displayTime":{"type":"string","nullable":true,"description":"Display-formatted race time or gap as shown on the classification: the\nwinner's elapsed time, a time gap such as +0.308, or laps down such as\n+4 Laps.","example":"1:38:57.094"},"laps":{"type":"number","nullable":true,"description":"Laps completed, null when not recorded.","example":78},"driver":{"description":"Driver who set this result.","allOf":[{"type":"object","properties":{"id":{"type":"string","description":"Stable identifier for the driver across seasons and series.","example":"6f1c1d80-1f4e-4b0e-9a2c-0f1b6d4a8e21"},"firstName":{"type":"string","nullable":true,"example":"Lando"},"lastName":{"type":"string","nullable":true,"example":"Norris"},"code":{"type":"string","nullable":true,"description":"Three-letter abbreviation used on timing screens.","example":"NOR"},"number":{"type":"number","nullable":true,"description":"The number this driver carried in THIS session, not the one they carry\ntoday, so a historical result keeps the number of its own era: a 2025 F1\nresult gives Verstappen 1 and Norris 4 even though they now carry 3 and 1.\nIdentical to the row's `carNumber`, and the field to key on when matching\nagainst live timing. Null where the classification records no number,\nwhich is most F1 sessions before 2006.","example":4}},"required":["id","firstName","lastName","code","number"]}]},"carNumber":{"type":"string","nullable":true,"description":"Number on the car in this session, as recorded on the classification, and\nthe field to key on when matching against timing data. Same value as\ndriver.number, kept as a string because some series use numbers with\nleading zeros.","example":"87"},"team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"shortName":{"type":"string","nullable":true},"color":{"type":"string","nullable":true}},"required":["id","name","shortName","color"]},"chassis":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"}},"required":["id","name"]},"engineManufacturer":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"}},"required":["id","name"]},"fastestLap":{"type":"object","properties":{"rank":{"type":"number","nullable":true},"time":{"type":"string","nullable":true},"lap":{"type":"number","nullable":true}},"required":["rank","time","lap"]},"status":{"type":"string","nullable":true,"description":"Finishing status from the series' official classification. The vocabulary\nis per sport, so branch on it per sport:\n- F1: OK for a classified finish, else DNF, DNS or DSQ.\n- F2, F3, Formula E: null for a classified finish, else DNF, DNS or DSQ.\n- NASCAR (Cup, Xfinity, Truck): Running means the car was still running at\n  the checkered flag, on the lead lap or not, and is the value for nearly\n  every finisher. Anything else is NASCAR's retirement reason, e.g.\n  Accident, Engine, Suspension, Brakes, DVP, Too Slow.\n- IndyCar: Running, Contact, Mechanical, Retired, Off Course, DNS.\n- MotoGP, Moto2, Moto3: INSTND (classified), OUTSTND (retired),\n  NOTFINISHFIRST, NOTSTARTED, DISQUALIFIED, NOTONRESTARTGRID, OUTOFLAPS.\n- WEC: Classified, Retired, Not classified, Disqualified.\nLaps down and the gap to the winner are in displayTime, not here. Null\nwhen not recorded.","example":"Running"},"points":{"type":"number","description":"Championship points awarded for this result.","example":25},"gap":{"type":"string","nullable":true},"interval":{"type":"string","nullable":true,"description":"Interval to the car ahead, on the same basis as `gap`. Null for the\nleader and outside enriched F1 sessions.","example":"+1.271"},"pitStops":{"type":"number","nullable":true,"description":"Pit stops made, null outside enriched F1 sessions.","example":2},"bestLapTime":{"type":"string","nullable":true,"description":"Best lap time from live timing, null outside enriched F1 sessions.","example":"1:13.221"},"bestLapNumber":{"type":"number","nullable":true,"description":"Lap on which the best time was set, null outside enriched F1 sessions.","example":71},"sectors":{"type":"object","properties":{"s1":{"type":"string","nullable":true},"s2":{"type":"string","nullable":true},"s3":{"type":"string","nullable":true}},"required":["s1","s2","s3"]},"tireStrategy":{"type":"array","items":{"type":"object","properties":{"compound":{"type":"string"},"laps":{"type":"number"},"isNew":{"type":"boolean"}},"required":["compound","laps","isNew"]}},"gridPosition":{"type":"number","nullable":true},"q1Time":{"type":"string","nullable":true},"q2Time":{"type":"string","nullable":true,"description":"Q2 lap time for qualifying sessions, null otherwise.","example":"1:11.278"},"q3Time":{"type":"string","nullable":true,"description":"Q3 lap time for qualifying sessions, null otherwise.","example":"1:10.954"}},"required":["id","position","lapTime","displayTime","laps","driver","carNumber","team","chassis","engineManufacturer","fastestLap","status","points","gap","interval","pitStops","bestLapTime","bestLapNumber","sectors","tireStrategy","gridPosition","q1Time","q2Time","q3Time"]}}}}},"400":{"description":"Invalid event or session ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Event or session not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"eventId","in":"path","description":"Unique identifier of the event","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","description":"Unique identifier of the session","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/locations":{"get":{"operationId":"get_v1_formula1_locations","summary":"List all Formula 1 circuit locations","description":"Retrieve a paginated list of all Formula 1 racing circuit locations (tracks/venues). Returns location information including circuit name, city, country, geographic coordinates, and track specifications. Includes both current and historic Formula 1 venues. Supports pagination with a maximum limit of 50 locations per page.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/locations?page=1&limit=20\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Circuits"],"responses":{"200":{"description":"Successfully retrieved paginated list of circuits.","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"data":{"description":"The page of results. Item shape depends on the endpoint.","type":"array","items":{"type":"object"}},"meta":{"description":"Pagination details for this response.","allOf":[{"type":"object","properties":{"page":{"type":"number","description":"Current page (1-indexed).","example":1},"limit":{"type":"number","description":"Page size used for this response (max 50).","example":20},"total":{"type":"number","description":"Total number of items across all pages.","example":858},"totalPages":{"type":"number","description":"Total number of pages at this limit.","example":43}},"required":["page","limit","total","totalPages"]}]}},"required":["data","meta"]},{"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the circuit/venue.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Venue name."},"latitude":{"type":"string","nullable":true,"description":"Latitude in decimal degrees, null when unknown.","example":"43.7347"},"longitude":{"type":"string","nullable":true,"description":"Longitude in decimal degrees, null when unknown.","example":"7.42056"},"city":{"type":"string","nullable":true,"description":"City or locality, null when unknown.","example":"Monte Carlo"},"timezone":{"type":"string","nullable":true,"description":"IANA timezone of the venue, null when unknown.","example":"Europe/Monaco"},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}},"required":["name","twoCode","threeCode"]}},"required":["id","name","latitude","longitude","city","timezone","country"]}}}}]}}}},"400":{"description":"Invalid query parameters — `page` or `limit` is not a positive integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","default":1}},{"name":"limit","in":"query","description":"Number of items per page (max: 50)","required":false,"schema":{"type":"integer","default":20}}]}},"/v1/formula1/locations/{id}":{"get":{"operationId":"get_v1_formula1_locations_id","summary":"Get circuit/location details by ID","description":"Retrieve detailed information about a specific Formula 1 circuit location by its unique ID. Returns comprehensive location data including full circuit specifications (track length, number of corners, DRS zones), facility information, historical significance, lap records, complete event history at the venue, and geographic details.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/locations/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Circuits"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the circuit/venue.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Venue name."},"latitude":{"type":"string","nullable":true,"description":"Latitude in decimal degrees, null when unknown.","example":"43.7347"},"longitude":{"type":"string","nullable":true,"description":"Longitude in decimal degrees, null when unknown.","example":"7.42056"},"city":{"type":"string","nullable":true,"description":"City or locality, null when unknown.","example":"Monte Carlo"},"timezone":{"type":"string","nullable":true,"description":"IANA timezone of the venue, null when unknown.","example":"Europe/Monaco"},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}},"required":["name","twoCode","threeCode"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"dateStart":{"format":"date-time","type":"string"},"dateEnd":{"format":"date-time","type":"string"},"season":{"type":"object","properties":{"id":{"type":"string"},"year":{"type":"number"}}}},"required":["id","name","dateStart","dateEnd","season"]}}},"required":["id","name","latitude","longitude","city","timezone","country","events"]}}}},"400":{"description":"Invalid circuit ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Location not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the circuit","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/seasons":{"get":{"operationId":"get_v1_formula1_seasons","summary":"List all Formula 1 seasons","description":"Retrieve a paginated list of all Formula 1 championship seasons. Returns season information including year, number of races, champions (driver and constructor), and season status. Covers seasons from 1950 to present. Supports pagination with a maximum limit of 50 seasons per page.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/seasons?page=1&limit=20\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Seasons"],"responses":{"200":{"description":"Successfully retrieved paginated list.","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"data":{"description":"The page of results. Item shape depends on the endpoint.","type":"array","items":{"type":"object"}},"meta":{"description":"Pagination details for this response.","allOf":[{"type":"object","properties":{"page":{"type":"number","description":"Current page (1-indexed).","example":1},"limit":{"type":"number","description":"Page size used for this response (max 50).","example":20},"total":{"type":"number","description":"Total number of items across all pages.","example":858},"totalPages":{"type":"number","description":"Total number of pages at this limit.","example":43}},"required":["page","limit","total","totalPages"]}]}},"required":["data","meta"]},{"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the season. Use this for the season detail endpoints.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"year":{"type":"number","description":"Championship year.","example":2025},"sportId":{"type":"string","description":"Sport the season belongs to.","example":"formula1"},"status":{"type":"string","nullable":true,"description":"Lifecycle status, null when unknown.","example":"completed"},"roundCount":{"type":"number","nullable":true,"description":"Number of rounds in the calendar, null when unknown.","example":24}},"required":["id","year","sportId","status","roundCount"]}}}}]}}}},"400":{"description":"Invalid query parameters — `page` or `limit` is not a positive integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","default":1}},{"name":"limit","in":"query","description":"Number of items per page (max: 50)","required":false,"schema":{"type":"integer","default":20}}]}},"/v1/formula1/seasons/{id}":{"get":{"operationId":"get_v1_formula1_seasons_id","summary":"Get season details by ID","description":"Retrieve detailed information about a specific Formula 1 season by its unique ID. Season IDs come from the season list endpoint. Returns comprehensive season data including complete race calendar, championship standings (both drivers and constructors), regulations, key statistics, and notable events from that season.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/seasons/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Seasons"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"season":{"type":"object","description":"Season identity and calendar summary."},"drivers":{"description":"Final (or current) driver championship standings.","type":"array","items":{"type":"object","properties":{"teams":{"description":"Teams the driver scored for during the season, with the rounds they participated in.","type":"array","items":{"type":"object"}},"id":{"type":"string","description":"Identifier of the driver.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"number","description":"Championship position.","example":1},"points":{"type":"number","description":"Championship points total.","example":437},"firstName":{"type":"string","nullable":true,"description":"Given name.","example":"Max"},"lastName":{"type":"string","nullable":true,"description":"Family name.","example":"Verstappen"},"code":{"type":"string","nullable":true,"description":"Three-letter abbreviation, null when not used.","example":"VER"},"number":{"type":"number","nullable":true,"description":"Racing number, null when unknown.","example":1}},"required":["teams","id","position","points","firstName","lastName","code","number"]}},"teams":{"description":"Final (or current) team championship standings.","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"number","description":"Championship position.","example":1},"points":{"type":"number","description":"Championship points total.","example":860},"name":{"type":"string","nullable":true,"description":"Common display name.","example":"McLaren"},"shortName":{"type":"string","nullable":true,"description":"Short display name.","example":"McLaren"},"color":{"type":"string","nullable":true,"description":"Primary branding color as a hex string.","example":"#FF8000"}},"required":["id","position","points","name","shortName","color"]}},"schedule":{"description":"Every event in the season calendar, in order.","type":"array","items":{"type":"object"}}},"required":["season","drivers","teams","schedule"]}}}},"400":{"description":"Invalid season ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Season not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the season","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/seasons/{id}/drivers":{"get":{"operationId":"get_v1_formula1_seasons_id_drivers","summary":"Get season driver statistics","description":"Retrieve comprehensive driver statistics for a specific Formula 1 season. Returns detailed performance data for all drivers who competed in the season, including championship points, race wins, podiums, pole positions, fastest laps, DNFs, and final championship position. Data is sorted by championship standings.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/seasons/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/drivers\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Seasons"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"teams":{"description":"Teams the driver drove for during the season.","type":"array","items":{"type":"object"}},"id":{"type":"string","description":"Identifier of the driver.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"firstName":{"type":"string","nullable":true,"description":"Given name.","example":"Max"},"lastName":{"type":"string","nullable":true,"description":"Family name.","example":"Verstappen"},"number":{"type":"number","nullable":true,"description":"Racing number, null when unknown.","example":1},"tla":{"type":"string","nullable":true,"description":"Three-letter abbreviation, null when not used.","example":"VER"},"country":{"type":"object","properties":{"name":{"type":"string"},"twoCode":{"type":"string"},"threeCode":{"type":"string"}},"required":["name","twoCode","threeCode"]},"position":{"type":"number","description":"Final championship position for the season.","example":1},"totalPoints":{"type":"number","description":"Championship points total.","example":437},"raceStarts":{"type":"number","description":"Race starts.","example":24},"raceWins":{"type":"number","description":"Race wins.","example":9},"racePodiums":{"type":"number","description":"Race podium finishes (P1-P3).","example":14},"avgRaceFinishingPosition":{"type":"number","nullable":true,"description":"Mean race finishing position across classified finishes, null with no data.","example":3.2},"topFiveFinishes":{"type":"number","description":"Race finishes in the top five.","example":16},"topTenFinishes":{"type":"number","description":"Race finishes in the top ten.","example":21},"bestRaceFinish":{"type":"number","nullable":true,"description":"Best race finishing position, null with no data.","example":1},"sprintStarts":{"type":"number","description":"Sprint starts.","example":6},"sprintWins":{"type":"number","description":"Sprint wins.","example":2},"sprintPodiums":{"type":"number","description":"Sprint podium finishes.","example":4},"avgSprintFinishingPosition":{"type":"number","nullable":true,"description":"Mean sprint finishing position, null with no data.","example":2.5},"bestSprintFinish":{"type":"number","nullable":true,"description":"Best sprint finishing position, null with no data.","example":1},"polePositions":{"type":"number","description":"Pole positions.","example":8},"avgQualifyingPosition":{"type":"number","nullable":true,"description":"Mean qualifying position, null with no data.","example":2.4},"fastestLaps":{"type":"number","description":"Fastest laps set.","example":5},"dnfs":{"type":"number","description":"Did-not-finish results.","example":2},"completionRate":{"type":"number","description":"Share of entered races completed, 0 to 1.","example":0.92},"totalLapsCompleted":{"type":"number","description":"Total laps completed across the season.","example":1342},"pointsPerRace":{"type":"number","description":"Average points scored per race start.","example":18.2}},"required":["teams","id","firstName","lastName","number","tla","country","position","totalPoints","raceStarts","raceWins","racePodiums","avgRaceFinishingPosition","topFiveFinishes","topTenFinishes","bestRaceFinish","sprintStarts","sprintWins","sprintPodiums","avgSprintFinishingPosition","bestSprintFinish","polePositions","avgQualifyingPosition","fastestLaps","dnfs","completionRate","totalLapsCompleted","pointsPerRace"]}}}}},"400":{"description":"Invalid season ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Season not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the season","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/seasons/{id}/teams":{"get":{"operationId":"get_v1_formula1_seasons_id_teams","summary":"Get season constructor/team statistics","description":"Retrieve comprehensive constructor (team) statistics for a specific Formula 1 season. Returns detailed performance data for all constructor teams that competed in the season, including championship points, race wins, podiums, pole positions, fastest laps, 1-2 finishes, and final constructors championship position. Data is sorted by constructors championship standings.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/seasons/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a/teams\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Seasons"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"drivers":{"type":"array","items":{"type":"object"}},"id":{"type":"string","description":"Identifier of the team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","description":"Common display name.","example":"McLaren"},"shortName":{"type":"string","nullable":true,"description":"Short display name.","example":"McLaren"},"fullName":{"type":"string","nullable":true,"description":"Full official entrant name.","example":"McLaren Formula 1 Team"},"color":{"type":"string","nullable":true,"description":"Primary branding color as a hex string.","example":"#FF8000"},"country":{"type":"object","properties":{"name":{"type":"string"},"twoCode":{"type":"string"},"threeCode":{"type":"string"}},"required":["name","twoCode","threeCode"]},"position":{"type":"number","description":"Final championship position for the season.","example":1},"totalPoints":{"type":"number","description":"Championship points total.","example":437},"raceEntries":{"type":"number","description":"Car entries across all races (two cars per race for most series).","example":48},"raceWins":{"type":"number","description":"Race wins.","example":9},"racePodiums":{"type":"number","description":"Race podium finishes (P1-P3).","example":14},"avgRaceFinishingPosition":{"type":"number","nullable":true,"description":"Mean race finishing position across classified finishes, null with no data.","example":3.2},"topFiveFinishes":{"type":"number","description":"Race finishes in the top five.","example":16},"topTenFinishes":{"type":"number","description":"Race finishes in the top ten.","example":21},"bestRaceFinish":{"type":"number","nullable":true,"description":"Best race finishing position, null with no data.","example":1},"sprintEntries":{"type":"number","description":"Car entries across all sprints.","example":12},"sprintWins":{"type":"number","description":"Sprint wins.","example":2},"sprintPodiums":{"type":"number","description":"Sprint podium finishes.","example":4},"avgSprintFinishingPosition":{"type":"number","nullable":true,"description":"Mean sprint finishing position, null with no data.","example":2.5},"bestSprintFinish":{"type":"number","nullable":true,"description":"Best sprint finishing position, null with no data.","example":1},"polePositions":{"type":"number","description":"Pole positions.","example":8},"avgQualifyingPosition":{"type":"number","nullable":true,"description":"Mean qualifying position, null with no data.","example":2.4},"fastestLaps":{"type":"number","description":"Fastest laps set.","example":5},"dnfs":{"type":"number","description":"Did-not-finish results.","example":2},"completionRate":{"type":"number","description":"Share of entered races completed, 0 to 1.","example":0.92},"totalLapsCompleted":{"type":"number","description":"Total laps completed across the season.","example":1342},"pointsPerEntry":{"type":"number","description":"Average points scored per car entry.","example":17.9}},"required":["drivers","id","name","shortName","fullName","color","country","position","totalPoints","raceEntries","raceWins","racePodiums","avgRaceFinishingPosition","topFiveFinishes","topTenFinishes","bestRaceFinish","sprintEntries","sprintWins","sprintPodiums","avgSprintFinishingPosition","bestSprintFinish","polePositions","avgQualifyingPosition","fastestLaps","dnfs","completionRate","totalLapsCompleted","pointsPerEntry"]}}}}},"400":{"description":"Invalid season ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Season not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the season","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/teams":{"get":{"operationId":"get_v1_formula1_teams","summary":"List all Formula 1 teams","description":"Retrieve a paginated list of all Formula 1 constructor teams. Returns basic team information including name, country, debut year, and branding colors. Supports pagination with a maximum limit of 50 teams per page.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/teams?page=1&limit=20\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Teams"],"responses":{"200":{"description":"Successfully retrieved paginated list of teams.","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"data":{"description":"The page of results. Item shape depends on the endpoint.","type":"array","items":{"type":"object"}},"meta":{"description":"Pagination details for this response.","allOf":[{"type":"object","properties":{"page":{"type":"number","description":"Current page (1-indexed).","example":1},"limit":{"type":"number","description":"Page size used for this response (max 50).","example":20},"total":{"type":"number","description":"Total number of items across all pages.","example":858},"totalPages":{"type":"number","description":"Total number of pages at this limit.","example":43}},"required":["page","limit","total","totalPages"]}]}},"required":["data","meta"]},{"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","nullable":true,"description":"Common display name.","example":"Red Bull"},"shortName":{"type":"string","nullable":true,"description":"Short display name.","example":"Red Bull"},"fullName":{"type":"string","nullable":true,"description":"Full official entrant name.","example":"Oracle Red Bull Racing"},"sportId":{"type":"string","description":"Sport this listing was requested for.","example":"formula1"},"color":{"type":"string","nullable":true,"description":"Primary branding color as a hex string.","example":"#3671C6"},"city":{"type":"string","nullable":true,"description":"Base city, null when unknown.","example":"Milton Keynes"},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}},"required":["name","twoCode","threeCode"]}},"required":["id","name","shortName","fullName","sportId","color","city","country"]}}}}]}}}},"400":{"description":"Invalid query parameters — `page` or `limit` is not a positive integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","default":1}},{"name":"limit","in":"query","description":"Number of items per page (max: 50)","required":false,"schema":{"type":"integer","default":20}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/teams/{id}":{"get":{"operationId":"get_v1_formula1_teams_id","summary":"Get team details by ID","description":"Retrieve detailed information about a specific Formula 1 constructor team by its unique ID. Returns comprehensive team data including full history, championship wins, notable drivers, technical partnerships, and historical performance statistics.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/teams/7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Teams"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Stable unique identifier of the team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"name":{"type":"string","nullable":true,"description":"Common display name.","example":"Red Bull"},"fullName":{"type":"string","nullable":true,"description":"Full official entrant name.","example":"Oracle Red Bull Racing"},"shortName":{"type":"string","nullable":true,"description":"Short display name.","example":"Red Bull"},"city":{"type":"string","nullable":true,"description":"Base city, null when unknown.","example":"Milton Keynes"},"country":{"type":"object","properties":{"name":{"type":"string","nullable":true},"twoCode":{"type":"string","nullable":true},"threeCode":{"type":"string","nullable":true}},"required":["name","twoCode","threeCode"]},"powerUnit":{"type":"string","nullable":true,"description":"Current power unit supplier, null when unknown.","example":"Honda RBPT"},"color":{"type":"string","nullable":true,"description":"Primary branding color as a hex string.","example":"#3671C6"},"sportId":{"type":"string","description":"Sport this team was requested for.","example":"formula1"},"seasonParticipations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"year":{"type":"number"}},"required":["id","year"]}},"drivers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"teamSeasonParticipations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"year":{"type":"number"}},"required":["id","year"]}}},"required":["id","firstName","lastName"]}}},"required":["id","name","fullName","shortName","city","country","powerUnit","color","sportId","seasonParticipations","drivers"]}}}},"400":{"description":"Invalid team ID — must be a UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Team not found.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"id","in":"path","description":"Unique identifier of the team","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/export/laps":{"get":{"operationId":"get_v1_formula1_export_laps","summary":"Download a full Formula 1 season of lap-by-lap data","description":"Per-driver timing rows for every lap of every session: position, gaps, sectors, tyre compound and pit flags. last_lap_time on a row is the time of the previous completed lap, as broadcast.","tags":["Bulk Export"],"responses":{"200":{"description":"Streaming season laps file."},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Season not found."}},"parameters":[{"name":"season","in":"query","description":"Season year, e.g. 2024","required":true,"schema":{"type":"number"}},{"name":"format","in":"query","description":"csv (default) or ndjson","required":false,"schema":{"type":"string","enum":["csv","ndjson"]}}]}},"/v1/formula1/export/results":{"get":{"operationId":"get_v1_formula1_export_results","summary":"Download a full Formula 1 season of session results","description":"Every result for every session of the season as one download (CSV or NDJSON) instead of thousands of paginated calls.","tags":["Bulk Export"],"responses":{"200":{"description":"Streaming season results file."},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Season not found."}},"parameters":[{"name":"season","in":"query","description":"Season year, e.g. 2024","required":true,"schema":{"type":"number"}},{"name":"format","in":"query","description":"csv (default) or ndjson","required":false,"schema":{"type":"string","enum":["csv","ndjson"]}}]}},"/v1/formula1/standings/constructors":{"get":{"operationId":"get_v1_formula1_standings_constructors","summary":"Get Formula 1 constructor standings","description":"Retrieve the current Formula 1 World Constructors' Championship standings. Optionally pass a year to retrieve historical standings. If no year is provided, returns the current season's standings.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/standings/constructors?year=2024\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Standings"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the team.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"number","description":"Championship position.","example":1},"points":{"type":"number","description":"Championship points total.","example":860},"name":{"type":"string","nullable":true,"description":"Common display name.","example":"McLaren"},"shortName":{"type":"string","nullable":true,"description":"Short display name.","example":"McLaren"},"color":{"type":"string","nullable":true,"description":"Primary branding color as a hex string.","example":"#FF8000"}},"required":["id","position","points","name","shortName","color"]}}}}},"400":{"description":"Invalid `year` — must be an integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No standings found for that year.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"year","in":"query","required":false,"schema":{"type":"integer"}}]}},"/v1/formula1/standings/drivers":{"get":{"operationId":"get_v1_formula1_standings_drivers","summary":"Get Formula 1 driver standings","description":"Retrieve the current Formula 1 World Drivers' Championship standings. Optionally pass a year to retrieve historical standings. If no year is provided, returns the current season's standings.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/standings/drivers?year=2024\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Standings"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"teams":{"description":"Teams the driver scored for during the season, with the rounds they participated in.","type":"array","items":{"type":"object"}},"id":{"type":"string","description":"Identifier of the driver.","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"position":{"type":"number","description":"Championship position.","example":1},"points":{"type":"number","description":"Championship points total.","example":437},"firstName":{"type":"string","nullable":true,"description":"Given name.","example":"Max"},"lastName":{"type":"string","nullable":true,"description":"Family name.","example":"Verstappen"},"code":{"type":"string","nullable":true,"description":"Three-letter abbreviation, null when not used.","example":"VER"},"number":{"type":"number","nullable":true,"description":"Racing number, null when unknown.","example":1}},"required":["teams","id","position","points","firstName","lastName","code","number"]}}}}},"400":{"description":"Invalid `year` — must be an integer.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No standings found for that year.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"year","in":"query","required":false,"schema":{"type":"integer"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","txt"]}}]}},"/v1/formula1/live/sessions/{sessionId}/race-control":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_race_control","summary":"Get race control messages for a session","description":"Retrieve all race control messages (flags, penalties, safety car, etc.) for a session in chronological order.","tags":["F1 Race Control"],"responses":{"200":{"description":"Race control messages.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"message":{"type":"string","description":"Race control message text","example":"YELLOW FLAG IN TURN 4"},"category":{"type":"string","nullable":true,"description":"Message category","example":"Flag"},"flag":{"type":"string","nullable":true,"description":"Flag type","example":"YELLOW"},"scope":{"type":"string","nullable":true,"description":"Scope of the message","example":"Track"},"sector":{"type":"number","nullable":true,"description":"Sector number","example":3},"driverNumber":{"type":"string","nullable":true,"description":"Driver number involved","example":"44"},"lap":{"type":"number","description":"Lap number","example":15,"nullable":true},"utc":{"format":"date-time","type":"string","description":"UTC timestamp of the message","nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","message","category","flag","scope","sector","driverNumber","lap","utc","capturedAt"]}}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No race control messages found."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/live/sessions/{sessionId}/state":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_state","summary":"Get latest session state checkpoint","description":"Retrieve the most recent full state checkpoint for a session. Contains the complete serialised timing state as JSON.","tags":["F1 State"],"responses":{"200":{"description":"Latest state checkpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"state":{"type":"object","description":"Full serialised session state as JSON object"},"trigger":{"type":"string","description":"What triggered this checkpoint","example":"lap_change"},"lap":{"type":"number","description":"Lap number at checkpoint","example":10,"nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","state","trigger","lap","capturedAt"]}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No state checkpoint found."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/live/sessions/{sessionId}/timing":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_timing","summary":"Get latest timing data for a session","description":"Retrieve the most recent timing snapshot for every driver in a session, ordered by position.","tags":["F1 Timing"],"responses":{"200":{"description":"Latest timing data per driver.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"driverNumber":{"type":"string","description":"Driver number","example":"44"},"driverCode":{"type":"string","description":"Driver three-letter code","example":"HAM","nullable":true},"teamName":{"type":"string","description":"Team name","example":"Red Bull Racing","nullable":true},"teamColor":{"type":"string","description":"Team color hex code","example":"3671C6","nullable":true},"currentCompound":{"type":"string","nullable":true,"description":"Current tyre compound","example":"MEDIUM"},"position":{"type":"number","description":"Position in session","example":1,"nullable":true},"gapToLeader":{"type":"string","description":"Gap to leader","example":"+1.234","nullable":true},"intervalToAhead":{"type":"string","description":"Interval to car ahead","example":"+0.567","nullable":true},"lastLapTime":{"type":"string","nullable":true,"description":"Last lap time","example":"1:23.456"},"bestLapTime":{"type":"string","nullable":true,"description":"Best lap time","example":"1:22.345"},"sector1":{"type":"string","nullable":true,"description":"Sector 1 time","example":"28.123"},"sector2":{"type":"string","nullable":true,"description":"Sector 2 time","example":"33.456"},"sector3":{"type":"string","nullable":true,"description":"Sector 3 time","example":"21.789"},"inPit":{"type":"boolean","description":"Whether the driver is in the pit","example":false},"pitOut":{"type":"boolean","description":"Whether the driver just exited the pit","example":false},"numberOfPitStops":{"type":"number","description":"Number of pit stops made","example":2},"numberOfLaps":{"type":"number","description":"Number of laps completed","example":15},"retired":{"type":"boolean","description":"Whether the driver has retired","example":false},"lap":{"type":"number","description":"Lap number for this snapshot","example":10},"bestLapNumber":{"type":"number","description":"Lap number when best lap was achieved","example":8,"nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","driverNumber","driverCode","teamName","teamColor","currentCompound","position","gapToLeader","intervalToAhead","lastLapTime","bestLapTime","sector1","sector2","sector3","inPit","pitOut","numberOfPitStops","numberOfLaps","retired","lap","bestLapNumber","capturedAt"]}}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No timing data found for this session."}},"parameters":[{"name":"sessionId","in":"path","description":"Unique identifier of the session","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/live/sessions/{sessionId}/timing/drivers/{driverNumber}":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_timing_drivers_driverNumber","summary":"Get timing history for a specific driver","description":"Retrieve the full timing history for a specific driver in a session, ordered chronologically.","tags":["F1 Timing"],"responses":{"200":{"description":"Timing history for the driver.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"driverNumber":{"type":"string","description":"Driver number","example":"44"},"driverCode":{"type":"string","description":"Driver three-letter code","example":"HAM","nullable":true},"teamName":{"type":"string","description":"Team name","example":"Red Bull Racing","nullable":true},"teamColor":{"type":"string","description":"Team color hex code","example":"3671C6","nullable":true},"currentCompound":{"type":"string","nullable":true,"description":"Current tyre compound","example":"MEDIUM"},"position":{"type":"number","description":"Position in session","example":1,"nullable":true},"gapToLeader":{"type":"string","description":"Gap to leader","example":"+1.234","nullable":true},"intervalToAhead":{"type":"string","description":"Interval to car ahead","example":"+0.567","nullable":true},"lastLapTime":{"type":"string","nullable":true,"description":"Last lap time","example":"1:23.456"},"bestLapTime":{"type":"string","nullable":true,"description":"Best lap time","example":"1:22.345"},"sector1":{"type":"string","nullable":true,"description":"Sector 1 time","example":"28.123"},"sector2":{"type":"string","nullable":true,"description":"Sector 2 time","example":"33.456"},"sector3":{"type":"string","nullable":true,"description":"Sector 3 time","example":"21.789"},"inPit":{"type":"boolean","description":"Whether the driver is in the pit","example":false},"pitOut":{"type":"boolean","description":"Whether the driver just exited the pit","example":false},"numberOfPitStops":{"type":"number","description":"Number of pit stops made","example":2},"numberOfLaps":{"type":"number","description":"Number of laps completed","example":15},"retired":{"type":"boolean","description":"Whether the driver has retired","example":false},"lap":{"type":"number","description":"Lap number for this snapshot","example":10},"bestLapNumber":{"type":"number","description":"Lap number when best lap was achieved","example":8,"nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","driverNumber","driverCode","teamName","teamColor","currentCompound","position","gapToLeader","intervalToAhead","lastLapTime","bestLapTime","sector1","sector2","sector3","inPit","pitOut","numberOfPitStops","numberOfLaps","retired","lap","bestLapNumber","capturedAt"]}}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No timing data found for this driver."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}},{"name":"driverNumber","in":"path","description":"Driver number (e.g. \"1\", \"44\")","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/live/sessions/{sessionId}/timing/laps/{lap}":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_timing_laps_lap","summary":"Get timing data for a specific lap","description":"Retrieve the timing snapshot for every driver at a specific lap in a session, ordered by position.","tags":["F1 Timing"],"responses":{"200":{"description":"Timing data for the requested lap.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"driverNumber":{"type":"string","description":"Driver number","example":"44"},"driverCode":{"type":"string","description":"Driver three-letter code","example":"HAM","nullable":true},"teamName":{"type":"string","description":"Team name","example":"Red Bull Racing","nullable":true},"teamColor":{"type":"string","description":"Team color hex code","example":"3671C6","nullable":true},"currentCompound":{"type":"string","nullable":true,"description":"Current tyre compound","example":"MEDIUM"},"position":{"type":"number","description":"Position in session","example":1,"nullable":true},"gapToLeader":{"type":"string","description":"Gap to leader","example":"+1.234","nullable":true},"intervalToAhead":{"type":"string","description":"Interval to car ahead","example":"+0.567","nullable":true},"lastLapTime":{"type":"string","nullable":true,"description":"Last lap time","example":"1:23.456"},"bestLapTime":{"type":"string","nullable":true,"description":"Best lap time","example":"1:22.345"},"sector1":{"type":"string","nullable":true,"description":"Sector 1 time","example":"28.123"},"sector2":{"type":"string","nullable":true,"description":"Sector 2 time","example":"33.456"},"sector3":{"type":"string","nullable":true,"description":"Sector 3 time","example":"21.789"},"inPit":{"type":"boolean","description":"Whether the driver is in the pit","example":false},"pitOut":{"type":"boolean","description":"Whether the driver just exited the pit","example":false},"numberOfPitStops":{"type":"number","description":"Number of pit stops made","example":2},"numberOfLaps":{"type":"number","description":"Number of laps completed","example":15},"retired":{"type":"boolean","description":"Whether the driver has retired","example":false},"lap":{"type":"number","description":"Lap number for this snapshot","example":10},"bestLapNumber":{"type":"number","description":"Lap number when best lap was achieved","example":8,"nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","driverNumber","driverCode","teamName","teamColor","currentCompound","position","gapToLeader","intervalToAhead","lastLapTime","bestLapTime","sector1","sector2","sector3","inPit","pitOut","numberOfPitStops","numberOfLaps","retired","lap","bestLapNumber","capturedAt"]}}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No timing data found for this lap."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}},{"name":"lap","in":"path","description":"Lap number","required":true,"schema":{"type":"number"}}]}},"/v1/formula1/live/sessions/{sessionId}/weather":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_weather","summary":"Get latest weather for a session","description":"Retrieve the most recent weather snapshot for a session (air/track temperature, humidity, wind, rainfall, pressure).","tags":["F1 Weather"],"responses":{"200":{"description":"Latest weather snapshot.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"airTemp":{"type":"string","description":"Air temperature","example":"25.3","nullable":true},"trackTemp":{"type":"string","description":"Track temperature","example":"42.1","nullable":true},"humidity":{"type":"string","description":"Humidity percentage","example":"55","nullable":true},"windSpeed":{"type":"string","description":"Wind speed","example":"3.2","nullable":true},"windDirection":{"type":"string","description":"Wind direction in degrees","example":"180","nullable":true},"rainfall":{"type":"string","description":"Rainfall indicator","example":"0","nullable":true},"pressure":{"type":"string","description":"Atmospheric pressure","example":"1013.25","nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","airTemp","trackTemp","humidity","windSpeed","windDirection","rainfall","pressure","capturedAt"]}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No weather data found."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/live/sessions/{sessionId}/weather/history":{"get":{"operationId":"get_v1_formula1_live_sessions_sessionId_weather_history","summary":"Get weather history for a session","description":"Retrieve all weather snapshots recorded during a session in chronological order.","tags":["F1 Weather"],"responses":{"200":{"description":"Weather snapshot history.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Unique identifier","example":1},"sessionId":{"type":"string","description":"Session identifier"},"airTemp":{"type":"string","description":"Air temperature","example":"25.3","nullable":true},"trackTemp":{"type":"string","description":"Track temperature","example":"42.1","nullable":true},"humidity":{"type":"string","description":"Humidity percentage","example":"55","nullable":true},"windSpeed":{"type":"string","description":"Wind speed","example":"3.2","nullable":true},"windDirection":{"type":"string","description":"Wind direction in degrees","example":"180","nullable":true},"rainfall":{"type":"string","description":"Rainfall indicator","example":"0","nullable":true},"pressure":{"type":"string","description":"Atmospheric pressure","example":"1013.25","nullable":true},"capturedAt":{"format":"date-time","type":"string","description":"Timestamp when data was captured"}},"required":["id","sessionId","airTemp","trackTemp","humidity","windSpeed","windDirection","rainfall","pressure","capturedAt"]}}}}},"401":{"description":"Missing or invalid API key. Send your key in the `X-API-Key` header."},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"No weather data found."}},"parameters":[{"name":"sessionId","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}/telemetry/positions":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId_telemetry_positions","summary":"Where every car was on track, through a session","description":"Ordered position samples for every driver in a session: `[secondsIntoSession, trackFraction]`, where trackFraction runs from 0 at the start/finish line to just under 1 on the approach back to it. `lapEnds` marks each line crossing so samples can be cut into laps. This is the feed behind a moving-map replay.\n\nMost sessions are served at `resolution: \"fine\"` - map-matched from the 0.25s position feed and bounded by `accuracyM` metres, roughly 90 samples per lap placed where the motion actually bends. Sessions without matched curves fall back to `resolution: \"coarse\"`, about 12 samples per lap, which locates a car within a corner rather than through it. Coverage is every race and qualifying session from 2019, plus 2026 practice and sprints.\n\nPass `?driver=VER` to fetch a single car; a full race is several megabytes.\n\nSessions whose recorded POSITIONS are untrustworthy are withheld and return 404 with the reason. A session with faulty pedal channels still serves here in full, because that fault does not touch position.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/{eventId}/sessions/{sessionId}/telemetry/positions?driver=VER\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Telemetry"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"duration":{"type":"number","example":6062.5,"description":"Session length covered by these samples, seconds."},"lapLengthM":{"type":"number","nullable":true,"example":4714,"description":"Lap length in metres, null when unknown."},"resolution":{"type":"string","example":"fine","enum":["fine","coarse"],"description":"\"fine\" is map-matched from the 0.25s position feed and bounded by accuracyM. \"coarse\" is the mini-sector fallback: roughly 12 points per lap, which places a car within a corner rather than through it."},"accuracyM":{"type":"number","nullable":true,"example":5,"description":"Upper bound in metres on how far a drawn car can sit from the recorded one. Null for coarse sessions, where no such bound is claimed."},"quality":{"type":"string","example":"ok","description":"Telemetry quality, as on the per-driver telemetry route. Sessions whose recorded POSITIONS are untrustworthy are not served here at all."},"qualityNote":{"type":"string","nullable":true,"example":null,"description":"Why the grade is not \"ok\"; null when it is."},"drivers":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","example":"VER","description":"Three-letter driver abbreviation."},"samples":{"type":"array","items":{"type":"array","items":{"type":"number"}},"example":[[0,0.0121],[1.4,0.0308]],"description":"Ordered [secondsIntoSession, trackFraction] pairs. trackFraction is where the car is around the lap, 0 at the start/finish line and approaching 1 just before it. Gaps mean the car was not on track."},"lapEnds":{"type":"array","items":{"type":"array","items":{"type":"number"}},"example":[[1,94.6],[2,187.1]],"description":"Ordered [lapNumber, secondsIntoSession] pairs marking each start/finish crossing, so samples can be segmented into laps."}},"required":["code","samples","lapEnds"]}}},"required":["sessionId","duration","lapLengthM","resolution","accuracyM","quality","qualityNote","drivers"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Not an F1 session, the session does not belong to this event, no timed position data for this session or driver, or the session is withheld on data quality; withheld sessions say why in the error message."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"eventId","in":"path","description":"Event id.","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","description":"Session id.","required":true,"schema":{"type":"string"}},{"name":"driver","in":"query","description":"Three-letter driver abbreviation, e.g. VER. Omit for every driver.","required":false,"schema":{"type":"string","example":"VER"}}]}},"/v1/formula1/events/{eventId}/sessions/{sessionId}/telemetry/drivers/{code}":{"get":{"operationId":"get_v1_formula1_events_eventId_sessions_sessionId_telemetry_drivers_code","summary":"Sub-lap telemetry for one driver in a session","description":"Every lap the driver completed, each cut into equal slices of track with mean and minimum speed, throttle, brake, DRS and distance to the car ahead. Because the slices are fixed pieces of tarmac rather than fixed intervals of time, the same index compares directly across laps and across drivers.\n\nCoverage runs from 2019 and includes practice, qualifying, sprint and race sessions. Data is written after a session ends and does not change afterwards.\n\nSessions missing some laps are served with `quality: \"partial\"` and a `qualityNote` saying so. When specific recorded channels are known to be wrong (a faulty source feed), the session is served with `quality: \"degraded\"`: the faulty channels are listed in `withheldChannels` and their values are null, and everything else is real. A session wrong in a way that cannot be isolated to channels is refused, and the 404 message carries the recorded reason.\n\n### Usage\n```bash\ncurl -X GET \"https://formula-1.jojapi.net/v1/formula1/events/{eventId}/sessions/{sessionId}/telemetry/drivers/VER\" \\\n -H \"X-JoJAPI-Key: YOUR_API_KEY\"\n```","tags":["F1 Telemetry"],"responses":{"200":{"description":"Response 200","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","example":"7c9a4314-8d6f-4f6a-9bfe-2f1d56a30b6a"},"driverCode":{"type":"string","example":"VER","description":"Three-letter driver abbreviation."},"nSectors":{"type":"number","example":12,"description":"Mini-sectors per lap in this session."},"quality":{"type":"string","example":"ok","description":"Telemetry quality for this session. \"ok\" is sound; \"partial\" is missing some laps and says so in qualityNote; \"degraded\" means specific source channels are known faulty, listed in withheldChannels and nulled, while everything else is real. Sessions wrong beyond isolable channels return 404 with the reason in the message."},"qualityNote":{"type":"string","nullable":true,"example":null,"description":"Why the grade is not \"ok\"; null when it is."},"withheldChannels":{"example":[],"description":"Channels withheld because the source feed recorded them wrong (e.g. \"throttle\", \"brake\"). Their fields are null on every sector. Empty when the grade is \"ok\" or \"partial\".","type":"array","items":{"type":"string"}},"laps":{"type":"array","items":{"type":"object","properties":{"lap":{"type":"number","example":34},"lapTime":{"type":"string","nullable":true,"example":"1:32.401","description":"Lap time as the timing feed reported it."},"compound":{"type":"string","nullable":true,"example":"MEDIUM"},"position":{"type":"number","nullable":true,"example":4,"description":"Track position on this lap."},"inPit":{"type":"boolean","example":false,"description":"The car was in the pit lane on this lap."},"sectors":{"type":"array","items":{"type":"object","properties":{"sector":{"type":"number","example":7,"description":"Mini-sector index, 0-based, in track order."},"lapFraction":{"type":"number","nullable":true,"example":0.583,"description":"Where the sector starts as a fraction of the lap, 0..1."},"speedMean":{"type":"number","nullable":true,"example":271.4,"description":"Mean speed across the sector, km/h."},"speedMin":{"type":"number","nullable":true,"example":88.2,"description":"Slowest speed reached in the sector, km/h."},"throttlePct":{"type":"number","nullable":true,"example":74.1,"description":"Mean throttle pedal position, 0..100."},"brakePct":{"type":"number","nullable":true,"example":18.6,"description":"Share of samples with the brake applied, 0..100."},"drsPct":{"type":"number","nullable":true,"example":0,"description":"Share of samples with DRS open, 0..100. Always 0 from 2026, which has no DRS."},"gapAheadM":{"type":"number","nullable":true,"example":41.2,"description":"Median distance to the car ahead across the sector, metres."},"gapAheadMinM":{"type":"number","nullable":true,"example":12.8,"description":"Closest the car ahead came within the sector, metres."},"driverAhead":{"type":"string","nullable":true,"example":"16","description":"Racing number of the car ahead, when the feed resolved one."}},"required":["sector","lapFraction","speedMean","speedMin","throttlePct","brakePct","drsPct","gapAheadM","gapAheadMinM","driverAhead"]}}},"required":["lap","lapTime","compound","position","inPit","sectors"]}}},"required":["sessionId","driverCode","nSectors","quality","qualityNote","withheldChannels","laps"]}}}},"401":{"description":"Unauthorized — invalid or missing `X-API-Key` header.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}},"402":{"description":"Plan upgrade required. Returned when the endpoint needs a higher plan tier, or when the request came from a third-party browser page (CORS) on a plan without browser access. Body: { message, requiredTier, currentTier, upgradeUrl }."},"404":{"description":"Not an F1 session, the session does not belong to this event, no telemetry for this driver, or the session is withheld on data quality; withheld sessions say why in the error message."},"429":{"description":"Rate limit exceeded — per-minute or monthly plan quota reached. Slow down or upgrade your plan.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":404,"description":"HTTP status code."},"message":{"type":"string","example":"Driver not found for this sport","description":"Human-readable explanation of what went wrong."},"error":{"type":"string","example":"Not Found","description":"HTTP reason phrase."}},"required":["statusCode","message"]}}}}},"parameters":[{"name":"eventId","in":"path","description":"Event id.","required":true,"schema":{"type":"string"}},{"name":"sessionId","in":"path","description":"Session id.","required":true,"schema":{"type":"string"}},{"name":"code","in":"path","description":"Three-letter driver abbreviation, e.g. VER.","required":true,"schema":{"type":"string","example":"VER"}}]}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-JoJAPI-Key","description":"Your JoJ API key."}}}}