Tutorial · 10 min · endpoints verified 2026-09-22
How to build an NBA matchup page
Follow the correct game identifier into one matchup response, then render team and player sections only when their samples are populated.
API coverage and endpoint overview: Explore the NBA API
Why this is hard
The hard part is identity and partial context, not layout
The matchup route assembles several useful blocks, but each block can have a different absence rule. A durable page needs one id chain and independent empty states.
- The NBA games response can expose both canonical and league-native ids.
- Team season stats can be null before a usable box-score sample exists.
- Last-five form is null until the route has the documented minimum sample.
- Player media and per-player season averages are independently nullable.
Path 1 · recommended
Have your AI agent build it
Use MCP for the canonical game list and REST for the NBA matchup package.
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 NBA matchup page. Get the NBA match list first and preserve every
identifier exactly as returned. Call the NBA matchup REST route with the id it
documents. Render team season stats, last five, rest days and players as
independent panels; if one block is null, keep the rest of the page useful.What the agent cannot reach
The matchup route is not an MCP tool. The agent must call it over REST and must not assume the shared match UUID is accepted where the route requires another game id.
Path 2 · hand-coded
Build it yourself
The workflow starts from the NBA-native game list because it publishes the identifier relationship the matchup route needs.
- 01
List NBA games and keep both ids
Request the NBA game list and preserve match_id and game_id in separate properties. Their names carry different contracts.
List NBA gamesbashcurl -s "https://api.bigballsdata.com/v1/nba/games?limit=10" \ -H "Authorization: Bearer $BBS_API_KEY" - 02
Follow the matchup identifier
Use the id documented by the matchup route. Fail visibly on a 400 rather than retrying the other id silently.
Fetch the matchup packagebashcurl -s "https://api.bigballsdata.com/v1/nba/games/$MATCH_ID/matchup" \ -H "Authorization: Bearer $BBS_API_KEY" - 03
Render each block independently
Let season stats, form, roster rows and head-to-head history declare their own availability. A null section should not erase populated siblings.
Keep null boundaries localtypescriptconst view = { meta: matchup.match_meta, homeStats: matchup.home_team?.season_stats ?? null, homeForm: matchup.home_team?.last_5 ?? null, homePlayers: matchup.home_team?.players ?? [], headToHead: matchup.h2h ?? null, };
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/nba/games | NBA-native games with the identifiers needed for detail routes | The safe starting point for the matchup id chain. | Free |
| GET | /v1/nba/games/:id/matchup | Match meta, team stats, form, players and head-to-head blocks | The page payload in one request. Read the identifier guide. | Free |
Pricing, honestly
The matchup page works on Free
The games and matchup routes have Free entry points. Optional modelled player tiers or rolling projections carry their own plan floor and should be added as separate panels.
Free matchup page
GET /v1/nba/games
GET /v1/nba/games/:id/matchupOptional Solo models
GET /v1/players/:id/tier
GET /v1/players/:id/rolling-stats- The primary page is Free.
- A null season block is a data state, not a paywall.
- Solo model endpoints are optional enrichments.
- Odds remain a separate Edge product.
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 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 the first preview does not invent
Keep every panel backed by its response block.
- No fake projected starters when a lineup is absent.
- No synthesized team rating from partial box-score fields.
- No image URL reconstructed from an NBA id.
Questions
- Which id does the matchup route take?
- Use the identifier documented and returned by the NBA games surface. Preserve canonical and native ids separately.
- Why can last_5 be null?
- The route withholds the block until it has the documented sample rather than returning a misleading partial form strip.
- Does a null season_stats block mean the route failed?
- No. It can mean the team has no qualifying box-score rows for that season while other matchup blocks remain useful.
- Are roster headshots guaranteed?
- No. headshot_url is nullable and needs an initials fallback.
Related APIs
Other APIs you can build with: