Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: DataSports Exports 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: Exports
x-displayName: Bulk exports
description: 'Bulk exports. For the Business and Enterprise plans. Get a whole league season as files: create an export, poll its status, then download. Exports are generated in the background from the same data the endpoints above serve; each account may create up to 20 per UTC day, and each one is kept for 7 days. Business reads one year back, so a season that ended before that window is refused (403 history_not_in_plan) on that plan.'
paths:
/v2/exports:
post:
operationId: exports.create
tags:
- Exports
summary: Create an export
description: 'Kicks off an export of a single league season. JSON body: league (DataSportsAPI league id), season (taken from /v2/leagues/{id}/seasons) and format, one of json (the default — a single season.json containing league, season, rounds, all fixtures, standings, top players and top teams exactly as the endpoints return them), csv or parquet (each giving two flat tables: fixtures and standings). The response is 202 with the export object, in status pending.
**Note:** Fixtures are collected round by round, so a competition our data source does not split into rounds (NBA and NHL regular seasons) produces an export without fixtures; the export’s error field lists whatever could not be read (“not included: topPlayers”). Because we mirror the source’s listing, a match that was postponed and replayed later may appear twice — once as the postponed fixture and once as the played one, each with its own id (Premier League 25/26: 381 fixtures, one of them postponed). Columns in the CSV / Parquet files — fixtures: fixture_id, sport, start_time, round, round_name, status, status_description, home_team_id, home_team, away_team_id, away_team, home_score, away_score, winner, venue; standings: table, primary, position, team_id, team, played, wins, draws, losses, scores_for, scores_against, points, zone.
**Plans:** Requires Business or Enterprise; any lower plan receives 403 endpoint_not_in_plan.'
x-plans:
- business
- enterprise
externalDocs:
description: Docs page
url: https://datasportsapi.com/docs/api/exports/create/
parameters: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
league:
type: integer
minimum: 1
description: Our league id.
season:
type: integer
minimum: 1
description: A season id of that league, from /v2/leagues/{id}/seasons.
format:
type: string
enum:
- json
- csv
- parquet
default: json
description: json writes a single season.json; csv and parquet each write a fixtures table and a standings table.
required:
- league
- season
responses:
'202':
description: Accepted
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/Export'
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 — the league does not exist, or the season does not belong to it
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: '- export_limit — the allowance of 20 exports per UTC day has been used up
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 -X POST -H \"Authorization: Bearer dsa_live_…\" \\\n \"https://api.datasportsapi.com/v2/exports\""
- lang: TypeScript
label: TypeScript
source: const { data, meta } = await client.exports.create({ league, season });
- lang: Python
label: Python
source: res = client.exports.create(league=league, season=season)
- lang: Go
label: Go
source: 'res, err := client.Exports.Create(ctx, &datasportsapi.ExportsCreateParams{League: league, Season: season})'
- lang: Shell
label: CLI
source: $ dsa exports create --league <league> --season <season>
get:
operationId: exports.list
tags:
- Exports
summary: Exports
description: 'Lists your 20 most recent exports, latest first; those that are ready come with newly issued download links.
**Plans:** Requires Business or Enterprise; any lower plan receives 403 endpoint_not_in_plan.'
x-plans:
- business
- enterprise
externalDocs:
description: Docs page
url: https://datasportsapi.com/docs/api/exports/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:
$ref: '#/components/schemas/Export'
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/exports\""
- lang: TypeScript
label: TypeScript
source: const { data, meta } = await client.exports.list();
- lang: Python
label: Python
source: res = client.exports.list()
- lang: Go
label: Go
source: res, err := client.Exports.List(ctx)
- lang: Shell
label: CLI
source: $ dsa exports list
/v2/exports/{id}:
get:
operationId: exports.get
tags:
- Exports
summary: Export status
description: 'Returns a single export. Check it every few seconds until status becomes ready (or failed); building a season takes anywhere from a few seconds (when cached) to a few minutes. files contains a download URL for each file, valid for one hour (see linksExpireAt); request the export again to get new links.
**Plans:** Requires Business or Enterprise; any lower plan receives 403 endpoint_not_in_plan.'
x-plans:
- business
- enterprise
externalDocs:
description: Docs page
url: https://datasportsapi.com/docs/api/exports/get/
parameters:
- name: id
in: path
required: true
description: export id issued by DataSportsAPI, a positive integer
schema:
type: integer
minimum: 1
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/Export'
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/exports/{id}\""
- lang: TypeScript
label: TypeScript
source: const { data, meta } = await client.exports.get(id);
- lang: Python
label: Python
source: res = client.exports.get(id)
- lang: Go
label: Go
source: res, err := client.Exports.Get(ctx, id)
- lang: Shell
label: CLI
source: $ dsa exports get <id>
components:
schemas:
ExportFile:
type: object
description: One file of a ready export.
properties:
name:
type: string
description: File name, e.g. fixtures.parquet or season.json.
bytes:
type: integer
description: Size in bytes.
contentType:
type: string
description: MIME type of the file.
url:
type: string
format: uri
description: Signed download link; no API key needed, valid until linksExpireAt.
required:
- name
- bytes
- contentType
- url
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
Export:
type: object
description: A season export (Business and up). Poll it until status is ready or failed.
properties:
id:
type: integer
description: The export's id, for polling.
league:
type: integer
description: Our league id, as you sent it.
season:
type: integer
description: The season id, as you sent it.
format:
type: string
enum:
- json
- csv
- parquet
description: The format you asked for.
status:
type: string
enum:
- pending
- running
- ready
- failed
description: Where the build stands.
error:
anyOf:
- type: string
- type: 'null'
description: 'Why a failed export failed or, on a ready one, which parts could not be read (e.g. "not included: topPlayers").'
fixtureCount:
anyOf:
- type: integer
- type: 'null'
description: How many fixtures the export holds, once it is ready.
createdAt:
type: string
format: date-time
description: When you started it.
finishedAt:
anyOf:
- type: string
format: date-time
- type: 'null'
description: When it became ready or failed.
files:
type: array
items:
$ref: '#/components/schemas/ExportFile'
description: One entry per file; empty until the export is ready.
linksExpireAt:
type: string
format: date-time
description: 'When the url values in files stop working: an hour after you read them.'
required:
- id
- league
- season
- format
- status
- files
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/