Tutorial · 10 min · endpoints verified 2026-09-22
How to build an NHL scoreboard
Render regulation, overtime and shootout states from the served period arrays, preserve nullable fields, and add push updates with a REST recovery path.
API coverage and endpoint overview: Explore the NHL API
Why this is hard
Hockey scoreboards have more states than three periods
A stable NHL card must handle scheduled games, regulation, overtime, shootouts and finals without deciding what an extra array value means before reading the game state.
- A fourth or fifth linescore entry needs the returned status and period context.
- Team logo URLs are nullable on NHL response paths, so abbreviation fallback is required.
- Goalie and skater data are different blocks and are not scoreboard substitutes.
- A connected socket can be quiet between events; REST remains the recovery source.
Path 1 · recommended
Have your AI agent build it
The MCP server can inspect hockey coverage and fetch the NHL match list. Use the REST matchup route for period detail and the documented WebSocket protocol for push delivery.
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_matchesLive, upcoming or historical matches for a sport or league.
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 scoreboard with Big Balls Sports Data.
Call get_coverage for ice_hockey, then get_matches scoped to league nhl.
Render scheduled, live and final states separately. Render the period arrays at
their actual length and use status/period to label overtime or shootout. Use a
team abbreviation when logo_url is null. Keep a REST fallback after WebSockets.What the agent cannot reach
MCP exposes the shared match list but not the NHL matchup route or WebSocket subscription. Use REST for those two layers after the canonical match list is working.
Path 2 · hand-coded
Build it yourself
The implementation reads state from the response and never hard-codes a live fixture, score or participant image.
- 01
Load the NHL schedule and score list
Scope both sport and league so the result is the NHL rather than every ice-hockey competition.
Fetch the canonical match listtypescriptconst API = 'https://api.bigballsdata.com'; const headers = { Authorization: `Bearer ${process.env.BBS_API_KEY}` }; const response = await fetch( `${API}/v1/matches?sport=ice_hockey&league=nhl&limit=20`, { headers }, ); if (!response.ok) throw new Error(`matches failed: ${response.status}`); const { data: games } = await response.json(); - 02
Render periods at their actual length
Zip the home and away arrays without padding them. Let the returned period and status decide whether an extra entry is overtime or shootout.
Shape the period cellstypescriptconst periods = (game.linescore?.home ?? []).map((home, index) => ({ index: index + 1, home, away: game.linescore?.away?.[index] ?? null, })); const homeMark = game.home_team?.logo_url ?? game.home_team?.abbreviation ?? 'HOME'; const awayMark = game.away_team?.logo_url ?? game.away_team?.abbreviation ?? 'AWAY'; - 03
Add push updates and terminal-state handling
Merge messages by canonical match id, retain periodic REST reconciliation, and stop the live cadence only after the API reports a terminal status.
Delivery contracttext1. Subscribe with the canonical match id. 2. Merge period, clock, score and status only when present. 3. Reconcile from REST after reconnecting. 4. Keep OT/SO labels derived from the latest served state.
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/matches?sport=ice_hockey&league=nhl | NHL schedule, status, score and available period linescores | The canonical list and source of match ids for each scoreboard card. | Free |
| GET | /v1/nhl/games/:game_id/matchup | NHL match meta, linescore, team context and roster blocks where populated | Optional detail drawer for one game. Team media fields remain nullable. Read the NHL linescore guide. | Free |
Pricing, honestly
Free builds the board; Pro adds push delivery
The NHL match list and period-score state have a Free entry point. Pro adds WebSocket delivery and full play-by-play; nullable team media and empty clocks still need fallbacks.
Free scoreboard state
GET /v1/matches?sport=ice_hockey&league=nhlPro push and play-by-play
WebSocket match-room subscription + GET /v1/nhl/games/:game_id/plays- Free is enough for schedules, statuses, scores and served period arrays.
- Pro WebSockets reduce polling latency but need reconnect reconciliation.
- Full NHL play-by-play has a Pro floor.
- A logo or headshot upgrade is not implied by the transport plan.
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 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 xG explorer
- 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 first scoreboard does not promise
The board stays inside the data that the match and matchup responses expose.
- It does not infer a shootout winner from an unlabeled extra period cell.
- It does not turn a missing team logo into an external hotlink guessed from an abbreviation.
- It does not present post-game player aggregates as in-game box-score updates.
Questions
- Can the scoreboard run on the free plan?
- Yes. The shared NHL match surface has a Free entry point. Pro is needed for WebSocket push and full play-by-play.
- How should I label overtime and shootout columns?
- Use the returned status and period fields together with the array length. Do not assume that every fourth entry is always the same stage.
- What should render when logo_url is null?
- Use the team abbreviation or a text fallback. Do not reconstruct an external logo URL from the team name.
- How do I recover after a socket disconnect?
- Refetch the REST match list, replace cards by canonical match id, then resume the room subscription.
Related APIs
Other APIs you can build with: