Skip to content
PuckAPI

Documentation

Everything you need to connect and query 15 hockey data endpoints.

Getting started

Authentication

Every request requires an API key. Pass it via header or query parameter:

bash
x-api-key: YOUR_API_KEY
# or
Authorization: Bearer YOUR_API_KEY
# or (MCP only)
?key=YOUR_API_KEY

Verify your email, then create an API key from the dashboard. Free accounts get 500 credits.

Base URL

text
https://mcp.puckapi.com

REST APIPOST /v1/{tool} with JSON body. Works with cURL, Python, any HTTP client.

MCPPOST /mcp via Streamable HTTP. Works with Claude Desktop, Claude Code, Cursor, and any MCP client.

Rate limits

Credit balanceRate limit
100 credits or more60 req/min
Under 100 credits10 req/min

The limit is the same on every plan. It is burst protection, not the spend boundary; credits are that, and they are enforced per request. Running low slows you down so you notice before the balance reaches zero.

Error handling

CodeMeaningWhat to do
400Invalid parametersCheck required fields and value types
401Invalid or missing API keyCheck your x-api-key header
402Insufficient creditsTop up your wallet or upgrade your plan
429Rate limit exceededWait and retry (see limits above)
500Server errorRetry with idempotency key. Credits auto-refund on server errors.

Pass x-idempotency-key or x-request-id headers to make retries duplicate-safe.

Data coverage

DataStatusCoverageVolume
Play-by-play
Every event with rink coordinates, strength state, zone, shot type, and the players involved: goals, shots, misses, blocks, faceoffs, hits, giveaways, takeaways, penalties.
21,980 of 22,067 completed games. The 87 gaps are preseason games before 2018, for which the source publishes no play data. Coordinates are present on locatable events; stoppages and period markers carry none.
Available2010-11 through current6,800,000+ events
Games
Game records and detail for supported regular season, playoff, and preseason matchups.
Historical coverage depends on supported seasons and source availability.
Available2010-11 through current23,000+
Players
Player search and player stat lookup across supported datasets.
AvailableBio, roster, position, supported stats4,800+
Goalies
Goalie stat lookup including save percentage, GAA, wins, shutouts, and time on ice. Shot-quality metrics (GSAX, high-danger save%) are not yet computed.
AvailableSupported goalie stat seasons1,509
Teams
Team metadata, abbreviations, divisions, conferences, and arenas.
AvailableActive and historical franchises represented in PuckAPI34
Standings + rankings
Standings, rankings, and supported advanced team metrics.
Do not treat standings as real-time unless freshness is shown separately.
AvailableSupported seasons and current-season snapshots494
Odds
Odds for supported games, books, and markets where available.
Coverage varies by sportsbook, game, market, and source availability.
Partial2019-20 through current107,000+
Line movement
Line movement data where multiple odds snapshots exist for a supported game and market.
Not every game, book, or market has line movement history.
PartialHistorical odds snapshots where availableOpening/current/closing snapshots
Head-to-head
Historical matchup context for supported teams and games.
AvailableSupported teams and gamesMatchup history

Coverage describes the datasets PuckAPI supports. Freshness and operational health are tracked separately.

Odds snapshot definitions

opening — Game-day morning lines, captured at ~12:00 UTC (~7-8am ET). Represents the odds available on the morning of the game.

closing — Final pre-game lines, captured at ~23:00 UTC. For evening games, this is the last available line before or shortly after puck drop.

Odds coverage currently documents DraftKings, FanDuel, BetMGM, and ESPN BET. Sportsbook availability varies by game, market, and source. Do not assume every book is available for every game. Games before the 2019-20 season return no odds data.

Response format

REST API

All successful REST responses wrap the result in a data key:

json
{ "data": { "teams": [...], "count": 32 } }

Error responses return:

json
{ "error": "Insufficient credits", "message": "This tool costs 5 credits, you have 2" }

MCP Protocol

MCP responses follow the standard MCP tool result format. The data is returned directly (no data wrapper). Both access methods return identical data, just different envelopes.

Conventions

Seasons8-digit season id, start year + end year (2024-25 and 2024-2025 also accepted). Example: 20242025.

Game IDsAssigned by the league, e.g. 2025020887. Get them from get_games or get_schedule.

Team abbreviations — Standard codes (BUF, TOR, NYR, EDM). Use list_teams if unsure.

Pagination — Endpoints use a limit parameter. No cursor or offset. Narrow your filters to get different slices of data.

Credits — Deducted before the request executes. Automatically refunded on server errors. Monthly credits are used first, then wallet balance.

Setup

Claude Desktop

Add to your claude_desktop_config.json:

json
{
  "mcpServers": {
    "puckapi": {
      "url": "https://mcp.puckapi.com/mcp?key=YOUR_API_KEY"
    }
  }
}

Claude Code

One command:

bash
claude mcp add puckapi https://mcp.puckapi.com/mcp?key=YOUR_API_KEY --transport streamable-http

REST / cURL

POST to /v1/{tool_name} with your params as JSON body. No MCP client needed:

bash
curl -X POST https://mcp.puckapi.com/v1/list_teams \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY"

With parameters:

bash
curl -X POST https://mcp.puckapi.com/v1/get_standings \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"season": "20242025"}'

Which endpoint should I use?

Start from what you want to do, not the API path.

Endpoint reference

15 endpoints grouped by credit cost. Each includes parameters, example requests in three formats, and documented response fields.

Static reference

1 credit/call
POST

list_teams

1 credit

All 32 active NHL teams with divisions, conferences, and arenas.

When to use: You need a reference list of teams -- team abbreviations for other endpoints, arena names for travel planning, or division/conference groupings for analysis.

Parameters
NameTypeRequiredDescription
conferencestringoptional"Eastern" or "Western"
divisionstringoptionalDivision name (e.g. "Atlantic")
Example request
{
  "tool": "list_teams",
  "arguments": {
    "conference": "Eastern",
    "division": "Atlantic"
  }
}
Example response
json
{
  "teams": [
    {
      "abbrev": "BUF",
      "name": "Sabres",
      "city": "Buffalo",
      "conference": "Eastern",
      "division": "Atlantic",
      "arena": "KeyBank Center"
    },
    {
      "abbrev": "TOR",
      "name": "Maple Leafs",
      "city": "Toronto",
      "conference": "Eastern",
      "division": "Atlantic",
      "arena": "Scotiabank Arena"
    },
    {
      "abbrev": "FLA",
      "name": "Panthers",
      "city": "Florida",
      "conference": "Eastern",
      "division": "Atlantic",
      "arena": "Amerant Bank Arena"
    }
  ]
}
Response fields
FieldTypeDescription
teams[].abbrevstring3-letter team code (e.g. "BUF")
teams[].namestringTeam name (e.g. "Sabres")
teams[].citystringCity name
teams[].conferencestringEastern or Western
teams[].divisionstringDivision name
teams[].arenastringHome arena name

Basic lookup

2 credits/call
POST

get_schedule

2 credits

Upcoming games for the next N days. Defaults to 7 days.

When to use: You want to know what games are coming up this week -- for a specific team or across the league. Useful for building game-day alerts or planning which games to watch.

Parameters
NameTypeRequiredDescription
teamstringoptionalTeam abbreviation (e.g. "BUF")
daysintegeroptionalDays ahead (1-30, default 7)
Example request
{
  "tool": "get_schedule",
  "arguments": {
    "team": "BUF",
    "days": 7
  }
}
Example response
json
{
  "games": [
    {
      "id": "2025021143",
      "gameDate": "2026-04-10",
      "startTime": "19:00:00",
      "homeTeam": "BUF",
      "awayTeam": "TOR",
      "homeTeamName": "Buffalo Sabres",
      "awayTeamName": "Toronto Maple Leafs",
      "venue": "KeyBank Center",
      "gameType": "regular"
    },
    {
      "id": "2025021187",
      "gameDate": "2026-04-12",
      "startTime": "19:30:00",
      "homeTeam": "FLA",
      "awayTeam": "BUF",
      "homeTeamName": "Florida Panthers",
      "awayTeamName": "Buffalo Sabres",
      "venue": "Amerant Bank Arena",
      "gameType": "regular"
    }
  ]
}
Response fields
FieldTypeDescription
games[].idstringUnique game ID
games[].gameDatestringDate (YYYY-MM-DD)
games[].startTimestringStart time (HH:MM:SS)
games[].homeTeamstringHome team abbreviation
games[].awayTeamstringAway team abbreviation
games[].homeTeamNamestringHome team full name
games[].awayTeamNamestringAway team full name
games[].venuestringArena name
games[].gameTypestringregular, playoff, or preseason
POST

search_players

2 credits

Find players by name, team, or position.

When to use: You need a player's ID to look up their stats, or you want to search a roster by position. For example, "find all active centers on the Sabres" or "look up Tage Thompson's player ID."

Parameters
NameTypeRequiredDescription
querystringrequiredSearch string (e.g. "Tage Thompson")
teamstringoptionalFilter by team abbreviation
positionstringoptionalG, D, C, LW, or RW
activebooleanoptionalActive players only (default true)
limitintegeroptionalMax results (1-50, default 10)
Example request
{
  "tool": "search_players",
  "arguments": {
    "query": "Thompson",
    "team": "BUF"
  }
}
Example response
json
{
  "players": [
    {
      "id": 8480208,
      "name": "Tage Thompson",
      "team": "BUF",
      "teamName": "Buffalo Sabres",
      "position": "C",
      "jerseyNumber": 72,
      "active": true
    }
  ]
}
Response fields
FieldTypeDescription
players[].idintegerPlayer ID (use in get_player_stats)
players[].namestringFull name
players[].firstNamestringFirst name
players[].lastNamestringLast name
players[].teamstringTeam abbreviation
players[].teamNamestringFull team name
players[].positionstringPosition code
players[].positionTypestringPosition type (F, D, or G)
players[].jerseyNumberintegerJersey number
players[].birthCountrystringBirth country
players[].activebooleanCurrently active
POST

get_standings

2 credits

Current standings with points, point pace, goal differential and goals for/against per game.

When to use: You want to see how teams rank in the league right now -- points, win percentage, goal differential, and goals for and against per game. The possession columns (Corsi, Fenwick, expected goals) are in the response but are not yet computed and come back null.

Parameters
NameTypeRequiredDescription
conferencestringoptional"Eastern" or "Western"
divisionstringoptionalDivision name (e.g. "Atlantic")
seasonstringoptionalSeason (e.g. "20252026", default current)
Example request
{
  "tool": "get_standings",
  "arguments": {
    "conference": "Eastern",
    "division": "Atlantic"
  }
}
Example response
json
{
  "standings": [
    {
      "rank": 1,
      "teamAbbrev": "FLA",
      "teamName": "Florida Panthers",
      "points": 112,
      "gamesPlayed": 80,
      "wins": 52,
      "losses": 20,
      "otLosses": 8,
      "pointPct": 0.683,
      "goalDiff": 48,
      "goalsForPerGame": 3.54,
      "goalsAgainstPerGame": 2.94,
      "corsiPct": null,
      "fenwickPct": null,
      "expectedGoalsFor": null,
      "expectedGoalsAgainst": null
    },
    {
      "rank": 2,
      "teamAbbrev": "TOR",
      "teamName": "Toronto Maple Leafs",
      "points": 106,
      "gamesPlayed": 80,
      "wins": 49,
      "losses": 23,
      "otLosses": 8,
      "pointPct": 0.65,
      "goalDiff": 31,
      "goalsForPerGame": 3.41,
      "goalsAgainstPerGame": 3.02,
      "corsiPct": null,
      "fenwickPct": null,
      "expectedGoalsFor": null,
      "expectedGoalsAgainst": null
    }
  ]
}
Response fields
FieldTypeDescription
standings[].rankintegerLeague or division rank
standings[].teamAbbrevstringTeam abbreviation
standings[].teamNamestringFull team name
standings[].pointsintegerTotal points
standings[].gamesPlayedintegerGames played
standings[].winsintegerWins
standings[].lossesintegerLosses
standings[].otLossesintegerOvertime losses
standings[].pointPctnumberPoints percentage
standings[].goalDiffintegerGoal differential
standings[].goalsForPerGamenumberGoals for per game
standings[].goalsAgainstPerGamenumberGoals against per game
standings[].corsiPctnumber|nullCorsi percentage (5v5 shot attempts). Not yet computed -- always null.
standings[].fenwickPctnumber|nullFenwick percentage (unblocked shots). Not yet computed -- always null.
standings[].expectedGoalsFornumberExpected goals for
standings[].expectedGoalsAgainstnumberExpected goals against

Stats + aggregation

5 credits/call
POST

get_games

5 credits

Query games by date range, team, season, game state, or type.

When to use: You're building a dataset for analysis -- pull all games from a date range, all playoff games for a team, or all final scores from last season. This is the workhorse endpoint for model training data.

Parameters
NameTypeRequiredDescription
date_fromstringoptionalStart date (YYYY-MM-DD)
date_tostringoptionalEnd date (YYYY-MM-DD)
teamstringoptionalTeam abbreviation
seasonstringoptionalSeason (e.g. "20252026")
game_statestringoptionalFUT, LIVE, FINAL, or OFF
game_typestringoptionalregular, playoff, or preseason
limitintegeroptionalMax results (1-500, default 100)
Example request
{
  "tool": "get_games",
  "arguments": {
    "team": "TOR",
    "date_from": "2026-03-01",
    "date_to": "2026-03-07",
    "game_state": "FINAL"
  }
}
Example response
json
{
  "games": [
    {
      "id": "2025020934",
      "season": "20252026",
      "gameDate": "2026-03-02",
      "startTime": "19:00:00",
      "homeTeam": "TOR",
      "awayTeam": "BOS",
      "homeScore": 4,
      "awayScore": 2,
      "gameState": "FINAL",
      "gameType": "regular",
      "venue": "Scotiabank Arena"
    },
    {
      "id": "2025020958",
      "season": "20252026",
      "gameDate": "2026-03-05",
      "startTime": "19:30:00",
      "homeTeam": "MTL",
      "awayTeam": "TOR",
      "homeScore": 1,
      "awayScore": 3,
      "gameState": "FINAL",
      "gameType": "regular",
      "venue": "Bell Centre"
    }
  ]
}
Response fields
FieldTypeDescription
games[].idstringUnique game ID
games[].seasonstringSeason code (e.g. "20252026")
games[].gameDatestringDate (YYYY-MM-DD)
games[].startTimestringStart time
games[].homeTeamstringHome team abbreviation
games[].awayTeamstringAway team abbreviation
games[].homeTeamNamestringHome team full name
games[].awayTeamNamestringAway team full name
games[].homeScoreintegerHome team score (FINAL only)
games[].awayScoreintegerAway team score (FINAL only)
games[].gameStatestringFUT, LIVE, FINAL, or OFF
games[].gameTypestringregular, playoff, or preseason
games[].venuestringArena name
POST

get_team_stats

5 credits

Detailed stats for a specific team including advanced metrics and league rankings.

When to use: You want a complete statistical profile of a team -- league rank, point pace, goal differential, and goals for and against. The Corsi, Fenwick and expected-goals columns are present but not yet computed.

Parameters
NameTypeRequiredDescription
teamstringrequiredTeam abbreviation (e.g. "BUF")
seasonstringoptionalSeason (e.g. "20252026")
Example request
{
  "tool": "get_team_stats",
  "arguments": {
    "team": "BUF",
    "season": "20252026"
  }
}
Example response
json
{
  "team": {
    "abbrev": "BUF",
    "name": "Sabres",
    "fullName": "Buffalo Sabres",
    "city": "Buffalo",
    "conference": "Eastern",
    "division": "Atlantic",
    "arena": "KeyBank Center"
  },
  "current_stats": {
    "rank": 14,
    "gamesPlayed": 82,
    "wins": 44,
    "losses": 28,
    "otLosses": 10,
    "points": 98,
    "pointPct": 0.598,
    "goalDiff": 12,
    "goalsForPerGame": 3.27,
    "goalsAgainstPerGame": 3.12,
    "corsiPct": null,
    "fenwickPct": null,
    "expectedGoalsFor": null,
    "expectedGoalsAgainst": null
  },
  "season": "20252026"
}
Response fields
FieldTypeDescription
team.abbrevstringTeam abbreviation
team.fullNamestringFull team name
team.conferencestringConference
team.divisionstringDivision
current_stats.rankintegerLeague rank
current_stats.gamesPlayedintegerGames played
current_stats.winsintegerWins
current_stats.lossesintegerLosses
current_stats.pointsintegerTotal points
current_stats.pointPctnumberPoints percentage
current_stats.goalDiffintegerGoal differential
current_stats.goalsForPerGamenumberGoals for per game
current_stats.goalsAgainstPerGamenumberGoals against per game
current_stats.corsiPctnumber|nullCorsi percentage. Not yet computed -- always null.
current_stats.fenwickPctnumberFenwick percentage
current_stats.expectedGoalsFornumberExpected goals for
current_stats.expectedGoalsAgainstnumberExpected goals against
POST

get_player_stats

5 credits

Player bio and goalie stats (if goalie). For skaters, returns bio info and team context.

When to use: You have a player ID (from search_players) and want their full profile -- bio, team, position, and for goalies, their complete stat line including GSAX and advanced metrics.

Parameters
NameTypeRequiredDescription
player_idintegerrequiredPlayer ID (from search_players)
Example request
{
  "tool": "get_player_stats",
  "arguments": {
    "player_id": 8480045
  }
}
Example response
json
{
  "player": {
    "id": 8480045,
    "name": "Ukko-Pekka Luukkonen",
    "team": "BUF",
    "teamName": "Buffalo Sabres",
    "position": "G",
    "jerseyNumber": 1,
    "birthDate": "1999-03-09",
    "birthCountry": "FIN",
    "heightInches": 77,
    "weightLbs": 220,
    "shootsCatches": "L"
  },
  "goalie_stats": {
    "gamesPlayed": 58,
    "gamesStarted": 55,
    "wins": 30,
    "losses": 20,
    "otLosses": 5,
    "savePct": 0.912,
    "gaa": 2.71,
    "gsax": null,
    "shutouts": 3,
    "highDangerSavePct": null,
    "rollingSavePct": null,
    "trend": null
  }
}
Response fields
FieldTypeDescription
player.idintegerPlayer ID
player.namestringFull name
player.teamstringTeam abbreviation
player.teamNamestringFull team name
player.positionstringPosition code
player.jerseyNumberintegerJersey number
player.birthDatestringBirth date
player.birthCountrystringBirth country
player.heightInchesintegerHeight in inches
player.weightLbsintegerWeight in pounds
player.shootsCatchesstringShoots/catches (L or R)
goalie_statsobject|nullGoalie stats (null for skaters)
goalie_stats.savePctnumberSave percentage
goalie_stats.gaanumberGoals against average
goalie_stats.gsaxnumberGoals saved above expected
POST

get_goalie_stats

5 credits

Goalie leaderboard sorted by save%, GAA, GSAX, or wins.

When to use: You want to rank goalies across the league or within a team. GSAX (goals saved above expected) is the advanced metric that tells you who's actually good versus who plays behind a strong defense.

Parameters
NameTypeRequiredDescription
teamstringoptionalFilter by team abbreviation
seasonstringoptionalSeason (e.g. "20252026")
min_gamesintegeroptionalMinimum games played (default 10)
sort_bystringoptionalsave_pct, gaa, gsax, or wins
limitintegeroptionalMax results (1-50, default 20)
Example request
{
  "tool": "get_goalie_stats",
  "arguments": {
    "sort_by": "gsax",
    "limit": 3
  }
}
Example response
json
{
  "goalies": [
    {
      "playerId": 8479361,
      "playerName": "Connor Hellebuyck",
      "team": "WPG",
      "gamesPlayed": 64,
      "wins": 38,
      "losses": 18,
      "savePct": 0.924,
      "gaa": 2.31,
      "gsax": null,
      "shutouts": 5
    },
    {
      "playerId": 8477424,
      "playerName": "Sergei Bobrovsky",
      "team": "FLA",
      "gamesPlayed": 55,
      "wins": 34,
      "losses": 14,
      "savePct": 0.918,
      "gaa": 2.48,
      "gsax": null,
      "shutouts": 4
    },
    {
      "playerId": 8480045,
      "playerName": "Ukko-Pekka Luukkonen",
      "team": "BUF",
      "gamesPlayed": 58,
      "wins": 30,
      "losses": 20,
      "savePct": 0.912,
      "gaa": 2.71,
      "gsax": null,
      "shutouts": 3
    }
  ]
}
Response fields
FieldTypeDescription
goalies[].playerIdintegerPlayer ID
goalies[].playerNamestringGoalie name
goalies[].teamstringTeam abbreviation
goalies[].teamNamestringFull team name
goalies[].gamesPlayedintegerGames played
goalies[].winsintegerWins
goalies[].lossesintegerLosses
goalies[].otLossesintegerOvertime losses
goalies[].savePctnumberSave percentage
goalies[].gaanumberGoals against average
goalies[].gsaxnumberGoals saved above expected
goalies[].shutoutsintegerShutouts
goalies[].highDangerSavePctnumberHigh-danger save percentage
goalies[].rollingSavePctnumberRolling save percentage (recent trend)
goalies[].trendstringPerformance trend (hot, cold, stable)
goalies[].restDaysintegerDays since last start
POST

get_skater_season_stats

5 credits

Skater leaderboard sorted by points, goals, assists, plus/minus, or shots.

When to use: You want to rank skaters across the league or within a team, with special-teams production and usage alongside the counting stats. Use get_goalie_stats for goaltenders and get_player_stats for one player in depth.

Parameters
NameTypeRequiredDescription
teamstringoptionalFilter by team abbreviation
seasonstringoptionalSeason (e.g. "20252026"). Defaults to current.
min_gamesintegeroptionalMinimum games played (default 10)
sort_bystringoptionalpoints, goals, assists, plus_minus, or shots (default points)
limitintegeroptionalMax results (1-50, default 20)
Example request
{
  "tool": "get_skater_season_stats",
  "arguments": {
    "season": "20242025",
    "sort_by": "points",
    "limit": 3
  }
}
Example response
json
{
  "skaters": [
    {
      "playerId": 8476453,
      "playerName": "Nikita Kucherov",
      "team": "TBL",
      "position": "RW",
      "gamesPlayed": 78,
      "goals": 37,
      "assists": 84,
      "points": 121,
      "plusMinus": 22,
      "shots": 265,
      "shootingPct": 0.1396,
      "avgToiPerGame": 1271
    }
  ],
  "count": 1
}
Response fields
FieldTypeDescription
skaters[].playerIdintegerPlayer ID
skaters[].playerNamestringSkater name
skaters[].teamstringTeam abbreviation
skaters[].teamNamestringFull team name
skaters[].positionstringPosition (C, LW, RW, D)
skaters[].gamesPlayedintegerGames played
skaters[].goalsintegerGoals
skaters[].assistsintegerAssists
skaters[].pointsintegerPoints
skaters[].plusMinusintegerPlus/minus
skaters[].pimintegerPenalty minutes
skaters[].powerPlayGoalsintegerPower play goals
skaters[].powerPlayPointsintegerPower play points
skaters[].shorthandedGoalsintegerShorthanded goals
skaters[].shorthandedPointsintegerShorthanded points
skaters[].gameWinningGoalsintegerGame-winning goals
skaters[].otGoalsintegerOvertime goals
skaters[].shotsintegerShots on goal
skaters[].shootingPctnumberShooting percentage, as a fraction
skaters[].faceoffPctnumberFaceoff win percentage, as a fraction
skaters[].avgToiPerGameintegerAverage time on ice per game, in SECONDS
skaters[].snapshotDatestringDate the season snapshot was taken (YYYY-MM-DD)
countintegerNumber of skaters returned
filtersobjectThe filters applied, echoed back

Multi-table

10 credits/call
POST

get_odds

10 credits

Odds for a specific game with optional bookmaker and snapshot type filters.

When to use: You have a game ID and want the betting lines -- moneyline, spread, and total from specific bookmakers. Filter by opening or closing lines to see how the market priced the game.

Parameters
NameTypeRequiredDescription
game_idstringrequiredGame ID (e.g. "2025020887")
bookmakerstringoptionalFilter by bookmaker (e.g. "draftkings")
snapshot_typestringoptional"opening" (game-day morning) or "closing" (final pre-game). Default returns both.
Example request
{
  "tool": "get_odds",
  "arguments": {
    "game_id": "2025020887",
    "bookmaker": "draftkings"
  }
}
Example response
json
{
  "game_id": "2025020887",
  "home_team": "BUF",
  "away_team": "TOR",
  "game_date": "2026-03-15",
  "odds": [
    {
      "bookmaker": "draftkings",
      "snapshotType": "opening",
      "mlHome": -115,
      "mlAway": -105,
      "mlHomeProb": 0.535,
      "mlAwayProb": 0.512,
      "spreadHome": -1.5,
      "spreadHomeOdds": 170,
      "spreadAway": 1.5,
      "spreadAwayOdds": -200,
      "total": 6,
      "totalOverOdds": -110,
      "totalUnderOdds": -110,
      "capturedAt": "2026-03-14T12:00:00Z"
    },
    {
      "bookmaker": "draftkings",
      "snapshotType": "closing",
      "mlHome": -125,
      "mlAway": 105,
      "mlHomeProb": 0.556,
      "mlAwayProb": 0.488,
      "spreadHome": -1.5,
      "spreadHomeOdds": 165,
      "spreadAway": 1.5,
      "spreadAwayOdds": -195,
      "total": 6.5,
      "totalOverOdds": -110,
      "totalUnderOdds": -110,
      "capturedAt": "2026-03-15T18:50:00Z"
    }
  ],
  "bookmaker_count": 1
}
Response fields
FieldTypeDescription
game_idstringGame ID
home_teamstringHome team abbreviation
away_teamstringAway team abbreviation
odds[].bookmakerstringBookmaker name
odds[].snapshotTypestringopening or closing
odds[].mlHomeintegerHome moneyline
odds[].mlAwayintegerAway moneyline
odds[].mlHomeProbnumberImplied home win probability
odds[].mlAwayProbnumberImplied away win probability
odds[].spreadHomenumberHome puck line
odds[].spreadHomeOddsintegerHome spread price
odds[].spreadAwaynumberAway puck line
odds[].spreadAwayOddsintegerAway spread price
odds[].totalnumberOver/under total
odds[].totalOverOddsintegerOver price
odds[].totalUnderOddsintegerUnder price
odds[].capturedAtstringTimestamp of snapshot
bookmaker_countintegerNumber of bookmakers returned
POST

get_game_detail

10 credits

Full game detail including odds snapshots and confirmed goalie starts.

When to use: You want everything about a single game in one call -- scores, odds from multiple bookmakers, and confirmed goalie starts. Saves you from making separate get_odds and search_players calls.

Parameters
NameTypeRequiredDescription
game_idstringrequiredGame ID (e.g. "2025020887")
Example request
{
  "tool": "get_game_detail",
  "arguments": {
    "game_id": "2025020887"
  }
}
Example response
json
{
  "game": {
    "id": "2025020887",
    "season": "20252026",
    "gameDate": "2026-03-15",
    "startTime": "19:00:00",
    "homeTeam": "BUF",
    "awayTeam": "TOR",
    "homeScore": 5,
    "awayScore": 3,
    "gameState": "FINAL",
    "gameType": "regular",
    "venue": "KeyBank Center"
  },
  "home_team": {
    "abbrev": "BUF",
    "fullName": "Buffalo Sabres",
    "conference": "Eastern",
    "division": "Atlantic",
    "arena": "KeyBank Center"
  },
  "away_team": {
    "abbrev": "TOR",
    "fullName": "Toronto Maple Leafs",
    "conference": "Eastern",
    "division": "Atlantic",
    "arena": "Scotiabank Arena"
  },
  "odds": [
    {
      "bookmaker": "draftkings",
      "snapshotType": "closing",
      "mlHome": -125,
      "mlAway": 105,
      "mlHomeProb": 0.556,
      "mlAwayProb": 0.488,
      "spreadHome": -1.5,
      "total": 6.5,
      "totalOverOdds": -110,
      "totalUnderOdds": -110
    },
    {
      "bookmaker": "fanduel",
      "snapshotType": "closing",
      "mlHome": -130,
      "mlAway": 110,
      "mlHomeProb": 0.565,
      "mlAwayProb": 0.476,
      "spreadHome": -1.5,
      "total": 6.5,
      "totalOverOdds": -108,
      "totalUnderOdds": -112
    }
  ],
  "goalie_starts": null
}
Response fields
FieldTypeDescription
game.idstringGame ID
game.gameDatestringDate
game.homeScoreintegerHome team score
game.awayScoreintegerAway team score
game.gameStatestringFUT, LIVE, FINAL, or OFF
home_team.abbrevstringHome team abbreviation
home_team.fullNamestringFull team name
away_team.abbrevstringAway team abbreviation
away_team.fullNamestringFull team name
odds[]arrayOdds snapshots from all bookmakers
goalie_startsobject|nullConfirmed goalie starts. The table backing this is empty, so it is null for every game today
goalie_starts.homeGoalieNamestringHome starting goalie
goalie_starts.awayGoalieNamestringAway starting goalie
POST

get_head_to_head

10 credits

Matchup history between two teams with win/loss records.

When to use: You're previewing a matchup and want to know the rivalry history -- who has the edge, recent results, and head-to-head record for a specific season or all-time.

Parameters
NameTypeRequiredDescription
team1stringrequiredFirst team abbreviation
team2stringrequiredSecond team abbreviation
seasonstringoptionalFilter to specific season
limitintegeroptionalMax games (1-100, default 20)
Example request
{
  "tool": "get_head_to_head",
  "arguments": {
    "team1": "BUF",
    "team2": "TOR",
    "season": "20252026"
  }
}
Example response
json
{
  "team1": "BUF",
  "team2": "TOR",
  "record": {
    "BUF": 2,
    "TOR": 1
  },
  "total_games": 3,
  "games": [
    {
      "id": "2025020412",
      "season": "20252026",
      "gameDate": "2025-12-14",
      "homeTeam": "TOR",
      "awayTeam": "BUF",
      "homeScore": 3,
      "awayScore": 4,
      "gameState": "FINAL",
      "venue": "Scotiabank Arena"
    },
    {
      "id": "2025020623",
      "season": "20252026",
      "gameDate": "2026-01-28",
      "homeTeam": "BUF",
      "awayTeam": "TOR",
      "homeScore": 2,
      "awayScore": 5,
      "gameState": "FINAL",
      "venue": "KeyBank Center"
    }
  ]
}
Response fields
FieldTypeDescription
team1stringFirst team abbreviation
team2stringSecond team abbreviation
recordobjectWin counts keyed by team abbreviation
record.[TEAM]integerWins for that team
total_gamesintegerTotal games in range
games[].idstringGame ID
games[].gameDatestringDate
games[].homeTeamstringHome team abbreviation
games[].awayTeamstringAway team abbreviation
games[].homeScoreintegerHome team score
games[].awayScoreintegerAway team score
POST

get_plays

10 credits

Play-by-play events with rink coordinates, strength state, and the players involved.

When to use: You are working at the event level: shot locations, what happened on a power play, every faceoff a centre took, or the sequence leading to a goal. Requires at least game_id, season, or player_id -- an unfiltered scan of 7 million events is not offered.

Parameters
NameTypeRequiredDescription
game_idstringoptionalNHL game ID (e.g. 2025020887)
seasonstringoptionalSeason ID, 8-digit (e.g. 20242025)
teamstringoptionalTeam abbreviation that owns the event
player_idnumberoptionalNHL player ID; matches any role on the event
typestringoptionalgoal, shot-on-goal, missed-shot, blocked-shot, faceoff, hit, giveaway, takeaway, penalty, stoppage, ...
strengthstringoptionalSkater strength from the event owner's view: 5v5, 5v4, 4v5, ...
zonestringoptionalO offensive, N neutral, D defensive
periodnumberoptionalPeriod number (4+ is overtime)
shot_attempts_onlybooleanoptionalOnly goals, shots, misses and blocks (Corsi events)
limitnumberoptionalMax events (default 200, max 1000)
offsetnumberoptionalPagination offset
Example request
{
  "tool": "get_plays",
  "arguments": {
    "game_id": "2024020601",
    "type": "goal"
  }
}
Example response
json
{
  "plays": [
    {
      "game_id": "2024020601",
      "event_id": 111,
      "season": "20242025",
      "period": 1,
      "time_in_period": "01:08",
      "seconds_elapsed": 68,
      "type": "goal",
      "team": "PIT",
      "strength": "5v4",
      "x_coord": -80,
      "y_coord": -10,
      "zone": "O",
      "shot_type": "tip-in",
      "scoring_player_id": 8479344,
      "assist1_player_id": 8482758,
      "assist2_player_id": 8482698,
      "goalie_in_net_id": 8480045,
      "away_score": 1,
      "home_score": 0
    }
  ],
  "summary": {
    "returned": 1,
    "scope": "this page of results, not the full filter",
    "by_type": {
      "goal": 1
    },
    "shot_attempts": 1,
    "goals": 1
  },
  "count": 1,
  "next_offset": null
}
Response fields
FieldTypeDescription
plays[].typestringEvent type, the NHL's own key
plays[].teamstringAbbreviation of the team that owns the event
plays[].strengthstringSkater count from the owner's view, e.g. 5v4
plays[].x_coordnumberRink x, -100..100 along the length
plays[].y_coordnumberRink y, -42..42 across
plays[].zonestringO, N or D
plays[].seconds_elapsednumberSeconds from the opening faceoff, continuous across periods
plays[].scoring_player_idnumberScorer on a goal; see also shooting_player_id, winning_player_id, hitting_player_id
summary.by_typeobjectCounts per event type, for this page of results only
next_offsetnumberOffset for the next page, or null when the page is the last
POST

get_shot_map

10 credits

Every shot attempt with rink coordinates, shot type, shooter and goalie.

When to use: You want to plot or model shot locations rather than read a list of events -- a shooter's season heat map, a team's attempts by zone, or the input to an expected-goals model. Filter by game, by player, or by season plus team.

Parameters
NameTypeRequiredDescription
game_idstringoptionalNHL game ID
seasonstringoptionalSeason ID, 8-digit; use with team
teamstringoptionalTeam abbreviation; use with season
player_idnumberoptionalNHL player ID of the shooter
strengthstringoptionalStrength filter, e.g. 5v5
Example request
{
  "tool": "get_shot_map",
  "arguments": {
    "game_id": "2024020601"
  }
}
Example response
json
{
  "shots": [
    {
      "type": "shot-on-goal",
      "x_coord": 62,
      "y_coord": -9,
      "shot_type": "wrist",
      "strength": "5v5",
      "team": "PIT",
      "shooter": 8471675,
      "goalie": 8480045,
      "game_id": "2024020601",
      "period": 1,
      "seconds_elapsed": 143
    }
  ],
  "summary": {
    "returned": 114,
    "capped_at": 2000,
    "by_type": {
      "shot-on-goal": 55,
      "missed-shot": 29,
      "blocked-shot": 20,
      "goal": 10
    }
  },
  "count": 114
}
Response fields
FieldTypeDescription
shots[].x_coordnumberRink x, -100..100
shots[].y_coordnumberRink y, -42..42
shots[].typestringgoal, shot-on-goal, missed-shot or blocked-shot
shots[].shot_typestringwrist, snap, slap, tip-in, backhand, deflected, wrap-around
shots[].shooternumberShooter's NHL player ID
shots[].goalienumberGoalie in net at the time
summary.capped_atnumberHard cap of 2,000 shots per call

Time-series

25 credits/call
POST

get_line_movement

25 credits

Time-series odds snapshots grouped by bookmaker. Shows how lines moved from open to close.

When to use: You're analyzing sharp money or building a betting model and need to see how odds changed over time. Opening vs. closing line differences reveal where the market moved, which is the strongest signal in sports betting.

Parameters
NameTypeRequiredDescription
game_idstringrequiredGame ID (e.g. "2025020887")
bookmakerstringoptionalFilter to one bookmaker
Example request
{
  "tool": "get_line_movement",
  "arguments": {
    "game_id": "2025020887",
    "bookmaker": "draftkings"
  }
}
Example response
json
{
  "game_id": "2025020887",
  "home_team": "BUF",
  "away_team": "TOR",
  "movement": {
    "draftkings": [
      {
        "bookmaker": "draftkings",
        "snapshotType": "opening",
        "mlHome": -115,
        "mlAway": -105,
        "spreadHome": -1.5,
        "total": 6,
        "capturedAt": "2026-03-15T12:00:00Z"
      },
      {
        "bookmaker": "draftkings",
        "snapshotType": "closing",
        "mlHome": -125,
        "mlAway": 105,
        "spreadHome": -1.5,
        "total": 6.5,
        "capturedAt": "2026-03-15T23:00:00Z"
      }
    ]
  }
}
Response fields
FieldTypeDescription
game_idstringGame ID
home_teamstringHome team abbreviation
away_teamstringAway team abbreviation
movement[book][]arrayChronological snapshots per bookmaker
movement[book][].snapshotTypestringopening or closing
movement[book][].mlHomeintegerHome moneyline at this snapshot
movement[book][].mlAwayintegerAway moneyline at this snapshot
movement[book][].spreadHomenumberHome puck line
movement[book][].totalnumberOver/under total
movement[book][].capturedAtstringTimestamp

Ready to start?

500 free credits on signup. No credit card required.

Get a free key