Tutorial · 9 min · endpoints verified 2026-09-22
How to build an NHL xG explorer
Rank the served leaderboard, make all-situations scope explicit, and keep unavailable model values separate from real zeroes.
API coverage and endpoint overview: Explore the NHL API
Why this is hard
Expected goals is useful only when its scope stays attached
An xG value without season, sample and strength-state context invites a false comparison. The explorer should make those qualifiers more visible than the ranking.
- The current leaderboard is all-situations, not a five-on-five split.
- Null xG means unavailable; it does not mean zero expected goals.
- Goals above expected is derived from goals and xG and needs the same sample.
- Different seasons can have different model availability.
Path 1 · recommended
Have your AI agent build it
Use MCP for coverage and player context, then call the NHL leaderboard over REST for the xG fields.
1. Connect the MCP server
Add the server in your MCP client and sign in with your Big Balls account. Your client registers itself and handles the token exchange — there is no key to copy.
{
"mcpServers": {
"bigballs-sports-data": {
"url": "https://mcp.bigballsdata.com/mcp"
}
}
}2. Tools your agent gets
get_player_statsPer-player career or per-season totals and per-game rates.
get_coverageMachine-readable map of what we hold and what we do not.
3. Ask for what you want
Paste this at your agent. It is written to make the model check coverage before it designs anything, which is what stops it inventing a field we do not serve.
Build an NHL expected-goals explorer. Check ice_hockey coverage, then
fetch /v1/nhl/leaders with stat=xg over REST. Label the board all-situations,
show season and games played, and keep null values out of numeric rankings.
Compare goals, xg and goals_above_xg without inventing five-on-five splits.What the agent cannot reach
The NHL leaderboard is REST-only in MCP today. The agent can inspect coverage and player stats, but must fetch the xG ranking over HTTP.
Path 2 · hand-coded
Build it yourself
The explorer reads the leaderboard in one call and carries its season and situation fields into every view.
- 01
Confirm xG coverage
Read the hockey coverage response before populating a season picker. Counting stats and computed xG can span different seasons.
Read hockey coveragebashcurl -s "https://api.bigballsdata.com/v1/coverage?sport=ice_hockey" \ -H "Authorization: Bearer $BBS_API_KEY" - 02
Fetch the xG leaderboard
Request the xG stat and keep the response season, situation and minimum-games context.
Fetch NHL xG leadersbashcurl -s "https://api.bigballsdata.com/v1/nhl/leaders?stat=xg&min_games=20&limit=100" \ -H "Authorization: Bearer $BBS_API_KEY" - 03
Rank only comparable rows
Exclude null model values from numeric ranking while preserving them in a separately labelled unavailable state.
Prepare comparable rowstypescriptconst ranked = leaders .filter((row) => row.xg != null && row.goals_above_xg != null) .sort((a, b) => b.xg - a.xg);
Reference
Every endpoint this tutorial uses
All on the gateway at api.bigballsdata.com. Verified against production on 2026-09-22.
| Method | Path | Returns | Why you need it | Plan |
|---|---|---|---|---|
| GET | /v1/nhl/leaders?stat=xg | All-situations NHL leaders with goals, xG and goals above expected | The ranking and comparison rows. Read the NHL xG scope guide. | Free |
| GET | /v1/coverage?sport=ice_hockey | Per-data-type availability and season depth | Constrains the season picker to modelled data. | Free |
Pricing, honestly
The xG leaderboard works on Free
The served leaderboard and coverage response are Free. Solo can add a position-adjusted player tier, but the explorer should keep that model separate from raw xG.
Free xG explorer
GET /v1/nhl/leaders?stat=xgOptional Solo tier
GET /v1/players/:id/tier- Free includes the xG ranking.
- The leaderboard is all-situations.
- Solo tiers are separate model output.
- No plan fills a model season that is not loaded.
More tutorials
Other build guides
- How to build a fantasy hockey app
- How to build a fantasy basketball app
- How to build an NBA scoreboard
- How to build an NHL scoreboard
- How to build an NBA props tracker
- How to build an NBA shot chart
- How to build an NBA matchup page
- How to build an NHL props tracker
- How to build an NHL goalie dashboard
- How to build a soccer xG app
- How to build a cricket app
- NFL fantasy football API tutorial
- How to build an NFL scouting tool
- How to build an NFL conditions analytics tool
- NFL betting model API tutorial
- NFL live game center API tutorial
- How to build an NCAAF scoreboard and live game center
- How to build college football rankings and conference standings
- How to build an NCAAF fantasy football app
- How to build an MLB live scoreboard
- How to build a fantasy baseball app
- How to build an MLB pitching dashboard
- How to build an MLB betting model
- How to build an MLB standings dashboard
- How to build a soccer fantasy app
- How to build a soccer betting model
- How to build a soccer live match center
- How to build a soccer player production board
- How to build a soccer fixture alert app
- How to build a soccer scouting tool
- How to build an NCAAF betting model
- How to build an NCAAF conditions analytics tool
- How to build a WNBA live scoreboard
- How to build a WNBA quarter tracker
- How to build a WNBA odds board
- How to build a WNBA schedule browser
- How to build a WNBA team-form tool
- How to build an NCAAB scoreboard
- How to build a March Madness archive
- How to build an NCAAB game-detail view
- How to build an NCAAB team-form dashboard
- How to build an NCAAB head-to-head tool
Known gaps
What this explorer does not claim
Keep the model scope explicit.
- No inferred five-on-five split.
- No shot map unless a separate coordinate surface supplies one.
- No replacement of null model values with zero.
Questions
- Is the leaderboard five-on-five?
- No. It is all-situations, and the explorer should label it that way.
- What does goals_above_xg mean?
- It is goals minus expected goals on the same served sample. Positive and negative values describe finishing relative to the model.
- Can I compare null xG as zero?
- No. Null means the model value is unavailable for that row.
- Do counting-stat and xG seasons always match?
- No. Read coverage per data type before enabling a season.
Related APIs
Other APIs you can build with: