Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: DataSports Catalog API
version: '2026-11-12'
summary: Real-time sports data over REST for 24 sports — scores, schedules, lineups, match statistics, tables, and team, player and league profiles.
description: 'One consistent JSON contract for 24 sports: fixtures and live scores, lineups and statistics, standings, plus teams, players and leagues, delivered in real time over REST, WebSocket and webhooks.
Successful responses use a `{ data, meta? }` envelope; failures return `{ error: { code, message } }` under a matching HTTP status. All ids are DataSportsAPI ids. Each component schema documents its fields, units and enum values, as does the data reference (https://datasportsapi.com/markdown/reference.md). The WebSocket stream, webhooks and widgets are documented at https://datasportsapi.com/docs/.
Availability: pre-launch. This documents the v2 contract; accounts, API keys and the SDK packages open with the public launch — until then, join the early-access list at https://datasportsapi.com/signup/. During the beta the Free plan allows 1,000 requests a day (100 a day after).'
contact:
name: DataSportsAPI
email: contact@noventra.dev
url: https://datasportsapi.com/contact/
servers:
- url: https://api.datasportsapi.com
description: Production
security:
- bearerAuth: []
tags:
- name: Catalog
x-displayName: Catalog
description: Catalog
paths:
/v2/sports:
get:
operationId: sports.list
tags:
- Catalog
summary: Sports
description: 'Lists all supported sports, each with the number of matches live right now. Matches the source has left open — 45 min without any change, with a kick-off further back than a match in that sport could run — do not count towards it. kind tells you which endpoint family serves the sport: fixtures, for sports served by the Fixtures, Teams and Leagues endpoints; races, for motorsport and cycling, which the Race sports endpoints cover (their fixture lists stay empty).
**Plans:** Every plan, Free included.'
x-plans:
- free
- starter
- pro
- business
- enterprise
externalDocs:
description: Docs page
url: https://datasportsapi.com/docs/api/catalog/sports-list/
parameters: []
responses:
'200':
description: OK
headers:
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
slug:
type: string
name:
type: string
kind:
$ref: '#/components/schemas/SportKind'
live:
type: integer
required:
- slug
- name
- kind
- live
meta:
type: object
description: count
properties:
count:
type: integer
required:
- data
'400':
description: 'Bad request (`bad_request`): the message lists the values the parameter accepts.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, unknown or revoked API key (`unauthorized`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'Refused: your plan does not include this endpoint (`endpoint_not_in_plan`), the requested data predates your plan''s history window (`history_not_in_plan`; see `historyFrom`), or the caller''s IP is missing from the account''s allowlist (`ip_not_allowed`, Business and Enterprise).'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (`not_found`), valid ids with no source data behind them (`no_data`, e.g. tracking of a fixture the source does not follow), or an endpoint that does not cover this sport (`not_supported`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Per-minute rate exceeded (`rate_limited`) or the period's quota spent (`quota_exceeded`); wait the `Retry-After` seconds.
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Our fault (`internal_error`); safe to retry with backoff.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Upstream data temporarily unavailable (`upstream_unavailable`); try again once the `Retry-After` seconds have passed.
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-codeSamples:
- lang: Shell
label: cURL
source: "curl -H \"Authorization: Bearer dsa_live_…\" \\\n \"https://api.datasportsapi.com/v2/sports\""
- lang: TypeScript
label: TypeScript
source: const { data, meta } = await client.sports.list();
- lang: Python
label: Python
source: res = client.sports.list()
- lang: Go
label: Go
source: res, err := client.Sports.List(ctx)
- lang: Shell
label: CLI
source: $ dsa sports list
/v2/coverage:
get:
operationId: sports.coverage
tags:
- Catalog
summary: Coverage
description: 'Coverage figures for the whole API in one call, open to every plan: entity totals, each sport’s league directory and how far back its headline competitions reach. The totals object counts how many teams, players, fixtures, leagues, seasons, venues, managers and referees have a DataSportsAPI id; each one can be fetched by that id, and the numbers never go down. The bySport list describes every sport’s directory — its categories (countries, tours, regions or games) with the leagues they hold, or the series for motorsport and cycling — together with up to ten headline competitions, each with its number of seasons and its first season; historyFrom is the earliest of those. The history object condenses the depth of all headline competitions into a median span in years and the oldest season. Old seasons are thinner than recent ones: results and tables usually go back further than lineups and statistics. updatedAt says when the figures were computed — totals every hour, directories once a day. A sport may be absent for a while after a restart, until its directory has been read again, and until the very first count is ready the endpoint answers 503 with Retry-After.
**Plans:** Every plan, Free included.'
x-plans:
- free
- starter
- pro
- business
- enterprise
externalDocs:
description: Docs page
url: https://datasportsapi.com/docs/api/catalog/sports-coverage/
parameters: []
responses:
'200':
description: OK
headers:
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Coverage'
required:
- data
'400':
description: 'Bad request (`bad_request`): the message lists the values the parameter accepts.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, unknown or revoked API key (`unauthorized`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'Refused: your plan does not include this endpoint (`endpoint_not_in_plan`), the requested data predates your plan''s history window (`history_not_in_plan`; see `historyFrom`), or the caller''s IP is missing from the account''s allowlist (`ip_not_allowed`, Business and Enterprise).'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (`not_found`), valid ids with no source data behind them (`no_data`, e.g. tracking of a fixture the source does not follow), or an endpoint that does not cover this sport (`not_supported`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Per-minute rate exceeded (`rate_limited`) or the period's quota spent (`quota_exceeded`); wait the `Retry-After` seconds.
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Our fault (`internal_error`); safe to retry with backoff.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Upstream data temporarily unavailable (`upstream_unavailable`); try again once the `Retry-After` seconds have passed.
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-codeSamples:
- lang: Shell
label: cURL
source: "curl -H \"Authorization: Bearer dsa_live_…\" \\\n \"https://api.datasportsapi.com/v2/coverage\""
- lang: TypeScript
label: TypeScript
source: const { data, meta } = await client.sports.coverage();
- lang: Python
label: Python
source: res = client.sports.coverage()
- lang: Go
label: Go
source: res, err := client.Sports.Coverage(ctx)
- lang: Shell
label: CLI
source: $ dsa sports coverage
components:
schemas:
SportKind:
type: string
enum:
- fixtures
- races
description: The group of endpoints that serves a sport’s data.
x-enumDescriptions:
fixtures: Head-to-head matches between two sides, served by /v2/fixtures, /v2/livescores, /v2/leagues/… .
races: Events in which a whole field competes (motorsport, cycling), served by /v2/races, /v2/series/… . Fixture endpoints return nothing for these sports.
Error:
type: object
description: The body of every failed request. Branch on error.code; the message may be reworded.
properties:
error:
type: object
properties:
code:
type: string
description: Stable, snake_case code, e.g. not_found. Part of the contract.
message:
type: string
description: A readable sentence for logs; never parse it.
historyFrom:
type: string
format: date
description: 'history_not_in_plan only: the first day your plan can read.'
required:
- code
- message
required:
- error
CoverageHistory:
type: object
description: A summary of how deep the headline competitions of all sports go.
properties:
leagues:
type: integer
description: Number of headline competitions (the `headline` lists of every sport) whose firstSeason is known.
medianYears:
anyOf:
- type: integer
- type: 'null'
description: Median number of years between those competitions’ first season and the current year; null when no first season is known.
oldestSeason:
anyOf:
- type: integer
- type: 'null'
description: Earliest firstSeason among those competitions; null when none is known.
required:
- leagues
- medianYears
- oldestSeason
CoverageTotals:
type: object
description: 'Counts of the entities that have a DataSportsAPI id, each of which can be fetched by that id. The numbers only rise: an id, once issued, is never changed or withdrawn.'
properties:
leagues:
type: integer
description: Competitions and leagues that have a DataSportsAPI id.
seasons:
type: integer
description: League seasons that have a DataSportsAPI id.
teams:
type: integer
description: 'Teams that have a DataSportsAPI id: clubs and national sides, plus the individual competitors of one-on-one sports such as tennis, MMA, darts and snooker.'
players:
type: integer
description: Players that have a DataSportsAPI id.
fixtures:
type: integer
description: Fixtures (matches), played and upcoming, that have a DataSportsAPI id.
venues:
type: integer
description: Venues that have a DataSportsAPI id.
managers:
type: integer
description: Managers and head coaches that have a DataSportsAPI id.
referees:
type: integer
description: Referees that have a DataSportsAPI id.
required:
- leagues
- seasons
- teams
- players
- fixtures
- venues
- managers
- referees
SportCoverage:
type: object
description: One sport’s league directory in numbers, and how far back its headline competitions go.
properties:
sport:
type: string
description: Slug of the sport, as listed by /v2/sports.
kind:
$ref: '#/components/schemas/SportKind'
description: The endpoint family that serves this sport’s data.
categories:
type: integer
description: Number of categories (countries, regions, tours or games) the sport’s league directory holds (GET /v2/categories?sport=).
leagues:
type: integer
description: Number of leagues across all those categories (GET /v2/leagues?category=); motorsport and cycling count series instead (GET /v2/series?category=).
historyFrom:
anyOf:
- type: integer
- type: 'null'
description: Earliest firstSeason found in `headline`; null if unknown.
headline:
type: array
items:
$ref: '#/components/schemas/CoverageLeague'
description: 'Up to ten headline competitions for the sport: the popular international competitions in its directory or, failing those, the first leagues of the directory, in that order.'
required:
- sport
- kind
- categories
- leagues
- historyFrom
- headline
Coverage:
type: object
description: 'The scope of the API in figures: how many entities carry a DataSportsAPI id, what each sport’s league directory holds and how far back its headline competitions go.'
properties:
updatedAt:
type: string
format: date-time
description: Time these figures were computed (ISO 8601). The totals are refreshed every hour, the per-sport directories once a day.
sports:
type: integer
description: Number of sports served — the same list as GET /v2/sports.
totals:
$ref: '#/components/schemas/CoverageTotals'
description: 'Counts of the entities that have a DataSportsAPI id, each of which can be fetched by that id. The numbers only rise: an id, once issued, is never changed or withdrawn.'
history:
$ref: '#/components/schemas/CoverageHistory'
description: How deep the headline competitions of all sports go, taken together.
bySport:
type: array
items:
$ref: '#/components/schemas/SportCoverage'
description: One entry per sport whose directory has been read, in the order of /v2/sports. Shortly after this endpoint is redeployed a sport can be absent until its directory has been read once.
required:
- updatedAt
- sports
- totals
- history
- bySport
CoverageLeague:
type: object
description: One headline competition of a sport, with the depth of its season list.
properties:
id:
type: integer
description: League id issued by DataSportsAPI (for motorsport and cycling, a series id).
name:
type: string
description: Name of the league, competition or series.
seasons:
type: integer
description: How many seasons its season list holds (GET /v2/leagues/{id}/seasons; motorsport and cycling use /v2/series/{id}/seasons).
firstSeason:
anyOf:
- type: integer
- type: 'null'
description: 'Start year of the oldest season in that list; null when no season label can be parsed. Older seasons carry less detail: results and tables usually reach further back than lineups and statistics.'
required:
- id
- name
- seasons
- firstSeason
headers:
RateLimit-Limit:
description: Your plan's request quota for the current period (UTC month on paid plans, UTC day on Free).
schema:
type: integer
Retry-After:
description: Seconds to wait before trying again.
schema:
type: integer
RateLimit-Remaining:
description: Requests still available in the current period.
schema:
type: integer
RateLimit-Reset:
description: Seconds until the period ends and the quota refills.
schema:
type: integer
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'Your secret API key: `Authorization: Bearer dsa_live_…`. Publishable widget keys (`dsa_pub_…`) work only for the endpoints widgets read, from the sites registered on them.'
externalDocs:
description: Documentation
url: https://datasportsapi.com/docs/