Skip to main content

The cross-league surface

The headline feature of v3.0.0 is that the same API works across every league. Once you know one league, you know them all.

One call, every league

Switching sports is a one-token change — the method name and the parameters are the same:

import sdv from "sportsdataverse";

await sdv.nba.espnNbaScoreboard({});
await sdv.nfl.espnNflScoreboard({ week: 1, season_type: 2 });
await sdv.nhl.espnNhlScoreboard({});
await sdv.mlb.espnMlbScoreboard({});
await sdv.wnba.espnWnbaScoreboard({});

That makes it trivial to write league-agnostic helpers. The snake_case alias is handy here — it composes cleanly from the league string:

async function gamesToday(league) {
const board = await sdv[league][`espn_${league}_scoreboard`]({});
return board.events ?? [];
}

for (const league of ["nba", "nfl", "nhl", "mlb"]) {
console.log(league, (await gamesToday(league)).length);
}

Scopes: which endpoints a league has

Not every endpoint applies to every league. Endpoints belong to a scope, and a league exposes an endpoint only when the scope matches:

ScopeApplies toExample endpoints
universalevery leaguescoreboard, summary, team_roster, standings, news
ncaacollege leaguesrankings, conference groupings
footballNFL, CFB, UFLdrive/play detail, betting endpoints
mlbMLBbaseball-specific feeds

So espnCfbRankings exists (CFB carries the ncaa scope) but espnNbaRankings does not:

typeof sdv.cfb.espnCfbRankings; // 'function'
typeof sdv.nba.espnNbaRankings; // 'undefined'

Multi-league sports: soccer & cricket

Soccer and cricket cover many competitions under one namespace, so they take an extra league slug:

await sdv.soccer.espnSoccerScoreboard({ league: "eng.1" }); // Premier League
await sdv.soccer.espnSoccerScoreboard({ league: "esp.1" }); // La Liga
await sdv.soccer.espnSoccerStandings({ league: "ita.1" }); // Serie A

There are also convenience namespaces for the big competitions (epl, laliga, seriea, bundesliga, ligue1, ucl, …) that pin the slug for you:

await sdv.epl.espnEplScoreboard({}); // same as soccer + { league: 'eng.1' }

Introspecting the surface at runtime

The full matrix is exported, so you can build menus, validate input, or just explore:

import sdv, { LEAGUES, WRAPPERS } from "sportsdataverse";

// Every league and its ESPN slugs
LEAGUES.map((l) => ({ prefix: l.prefix, sport: l.sport, league: l.league }));

// Every endpoint definition (116 of them)
WRAPPERS.map((w) => w.short);

// Every endpoint available on a given league (camelCase canonical names)
Object.keys(sdv.nfl).filter((k) => k.startsWith("espnNfl"));

Next steps