PyPython SDK
Sync for scripts, asyncio for services.
Two clients with the same methods: DataSportsAPI for notebooks and scripts, AsyncDataSportsAPI for asyncio services. Every object of the contract is a typed dict, so your editor knows the field names.
- Package
- datasportsapi
- Runs on
- Python 3.10+ · sync and asyncio
- Key
- DATASPORTSAPI_API_KEY
- Status
- Not published yet
- Install
- $ pip install datasportsapi
The install line goes live with the first release; nothing is on a public registry yet. Everything on this page describes the client as it will ship.
Install
One package for both the sync and the asyncio client.
shell$ pip install datasportsapi # or $ uv add datasportsapi $ poetry add datasportsapiAuthenticate
Create a key in your dashboard. With no argument the client reads DATASPORTSAPI_API_KEY; pass api_key when the key lives somewhere else.
client.pyfrom datasportsapi import DataSportsAPI client = DataSportsAPI() # reads DATASPORTSAPI_API_KEY # or explicitly client = DataSportsAPI(api_key="dsa_live_…")First calls
Methods follow the docs' grouping. Path parameters are positional, in path order; query parameters are keyword arguments with the API's own names. Each call returns the { data, meta } envelope.
first_calls.pylive = client.livescores.list(sport="football") for f in live["data"]: print(f["home"]["name"], f["homeScore"]["current"], "-", f["awayScore"]["current"], f["away"]["name"]) table = client.leagues.standings(17, season=76986)["data"] lineups = client.fixtures.lineups(480112)["data"]Errors
Each HTTP status raises its own exception, and every one exposes status, code, message and retry_after. Branch on code; leave the message to your logs.
errors.pyfrom datasportsapi import ( DataSportsAPIError, NotFoundError, PermissionDeniedError, RateLimitError, ) try: wp = client.fixtures.win_probability(480112) except PermissionDeniedError as e: # 403 if e.code == "endpoint_not_in_plan": show_upgrade_hint() except NotFoundError as e: # 404: not_found, no_data, not_supported hide_panel() except RateLimitError as e: # 429 once retries are spent if e.code == "quota_exceeded": pause_for(e.retry_after) except DataSportsAPIError as e: # anything else from the API log.warning("%s %s", e.status, e.code)Python error type for each HTTP status, and the codes each status can carry Status Exception error.code 400 BadRequestError bad_request401 AuthenticationError unauthorized403 PermissionDeniedError endpoint_not_in_planhistory_not_in_planws_not_availableorigin_not_allowedip_not_allowed404 NotFoundError not_foundno_datanot_supported429 RateLimitError rate_limitedquota_exceeded500 InternalServerError internal_error503 ServiceUnavailableError upstream_unavailablePaging
Endpoints that take a page parameter get a …_pages twin: a generator that requests the next page lazily and stops after the last one, or at max_pages.
paging.pyfor page in client.teams.fixtures_pages(42, type="recent", max_pages=4): for fixture in page["data"]: archive(fixture)asyncio
AsyncDataSportsAPI mirrors every method as a coroutine, so concurrent calls are a gather away. Use it as an async context manager to close the connection pool cleanly.
async_client.pyimport asyncio from datasportsapi import AsyncDataSportsAPI async def main() -> None: async with AsyncDataSportsAPI() as client: fixture, lineups = await asyncio.gather( client.fixtures.get(480112), client.fixtures.lineups(480112), ) print(fixture["data"]["status"]["description"]) asyncio.run(main())WebSocket stream
Businessclient.stream() takes care of the single-use ticket, the subscription, reconnecting and replaying after a drop, and folding each delta into the fixtures it tracks. The async client has the same stream with async for.
stream.pywith client.stream(["livescores", "fixture:480112"]) as stream: for frame in stream: if frame["type"] == "delta": print(frame["id"], frame["changes"]) in_play = stream.fixtures("livescores") # merged state, any timeChannels, frames and replay rules are in the WebSocket guide. Without a Business key the stream answers 403 ws_not_available.
Options
429 rate_limited and 503 are retried after Retry-After, twice by default. 429 quota_exceeded is raised at once, because only the reset fixes it.
options.pyclient = DataSportsAPI( api_key=None, # None: DATASPORTSAPI_API_KEY base_url=None, # None: DATASPORTSAPI_BASE_URL, then https://api.datasportsapi.com timeout=30.0, # seconds, per attempt max_retries=2, # rate_limited and 503 only )Base URL resolution: the option or flag first, then
DATASPORTSAPI_BASE_URL, thenhttps://api.datasportsapi.com.
From the endpoint pages
Every endpoint shows its Python call.
Other clients
Your key is one form away.
1,000 free requests a day during the beta. No card, no sales call.