Skip to content
datasportsAPI

TsTypeScript SDK

Typed calls for anywhere JavaScript runs.

One dependency-free package with types for every object in the contract. ESM and CommonJS builds, so it drops into a Node service, an edge function or a Bun script without a bundler dance.

Package
datasportsapi
Runs on
Node 22+ · Deno · Bun · browsers · edge
Key
DATASPORTSAPI_API_KEY
Status
Not published yet
Install
$ npm 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.

  1. Install

    A single package with nothing else pulled in. Use whichever package manager the project already has.

    shell
    $ npm install datasportsapi
    # or
    $ pnpm add datasportsapi
    $ bun add datasportsapi
  2. Authenticate

    Create a key in your dashboard and keep it on the server. Leave apiKey out and the client reads DATASPORTSAPI_API_KEY; pass it in when it comes from a secret manager instead.

    client.ts
    import { DataSportsAPI } from "datasportsapi";
    
    // Picks up DATASPORTSAPI_API_KEY from the environment
    export const client = new DataSportsAPI();
    
    // …or hand it over yourself
    export const scoped = new DataSportsAPI({ apiKey: await secrets.get("sports-key") });
  3. First calls

    Each endpoint is a method grouped the way the docs are. Path parameters go first, in the order the path lists them; query parameters follow as one object, using the API's own names. You get the { data, meta } envelope back, fully typed.

    first-calls.ts
    // Everything in play, one sport
    const { data: live } = await client.livescores.list({ sport: "football" });
    
    // A league table for one season
    const { data: table } = await client.leagues.standings(17, { season: 76986 });
    
    // Both sides' lineups for a fixture
    const { data: lineups } = await client.fixtures.lineups(480112);
  4. Errors

    Every HTTP status has its own error class, and each one carries the API's code, message and retryAfter. Decide what to do from the code; the message is for humans and can change.

    errors.ts
    import { DataSportsAPIError, NotFoundError, PermissionDeniedError, RateLimitError } from "datasportsapi";
    
    try {
      const { data } = await client.fixtures.winProbability(480112);
      drawCurve(data);
    } catch (err) {
      if (err instanceof PermissionDeniedError && err.code === "endpoint_not_in_plan") {
        showUpgradeHint(); // Free and Starter keys
      } else if (err instanceof NotFoundError && err.code === "not_supported") {
        hidePanel(); // not a football fixture
      } else if (err instanceof RateLimitError && err.code === "quota_exceeded") {
        pauseFor(err.retryAfter); // seconds until the quota resets
      } else if (err instanceof DataSportsAPIError) {
        log(err.status, err.code, err.message);
      } else {
        throw err;
      }
    }
    TypeScript error type for each HTTP status, and the codes each status can carry
    StatusError classerror.code
    400BadRequestErrorbad_request
    401AuthenticationErrorunauthorized
    403PermissionDeniedErrorendpoint_not_in_planhistory_not_in_planws_not_availableorigin_not_allowedip_not_allowed
    404NotFoundErrornot_foundno_datanot_supported
    429RateLimitErrorrate_limitedquota_exceeded
    500InternalServerErrorinternal_error
    503ServiceUnavailableErrorupstream_unavailable
  5. Paging

    Any endpoint that takes a page parameter also has a …Pages method: an async iterator that fetches the next page only when you ask for it and stops on the last one.

    paging.ts
    for await (const page of client.teams.fixturesPages(42, { type: "recent" }, { maxPages: 4 })) {
      console.log("page", page.meta.page);
      for (const fixture of page.data) archive(fixture);
    }
  6. WebSocket stream

    Business

    client.stream() handles the connection end to end: it requests a single-use ticket, subscribes to your channels, reconnects when the link drops, replays the frames you missed and applies each delta to its local copy of the fixtures.

    stream.ts
    const stream = client.stream(["livescores", "fixture:480112"]);
    
    stream.on("delta", (frame) => {
      console.log(frame.id, frame.changes); // a partial Fixture, already merged
    });
    stream.on("error", (err) => console.error(err.code));
    
    // The merged state of a channel, current at any moment
    const inPlay = stream.fixtures("livescores");
    
    stream.close();

    Channels, frames and replay rules are in the WebSocket guide. Without a Business key the stream answers 403 ws_not_available.

  7. Options

    Defaults suit most apps. When the API answers 429 rate_limited or 503, the client waits for the Retry-After it was given and tries again, up to twice by default. A 429 quota_exceeded is never retried: waiting a few seconds would not help.

    options.ts
    const client = new DataSportsAPI({
      apiKey: process.env.DATASPORTSAPI_API_KEY, // the default
      baseUrl: "https://api.datasportsapi.com",  // or DATASPORTSAPI_BASE_URL
      timeout: 30_000, // ms, per attempt
      maxRetries: 2,   // rate_limited and 503 only
    });

    Base URL resolution: the option or flag first, then DATASPORTSAPI_BASE_URL, then https://api.datasportsapi.com.

From the endpoint pages

Every endpoint shows its TypeScript call.

All endpoints

Other clients

Your key is one form away.

1,000 free requests a day during the beta. No card, no sales call.