Skip to content
PuckAPI

Documentation

27 hockey data endpoints over REST and MCP. One key, credits per call.

Coming from the NHL's own endpoints? See how they compare.

Your first call

Sign up for a free key (500 credits every month, no card), swap it in for YOUR_API_KEY, and send this. get_standings costs 2 credits.

Request

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

Response

json
{
  "standings": [
    {
      "rank": 1,
      "teamAbbrev": "COL",
      "teamName": "Colorado Avalanche",
      "points": 121,
      "gamesPlayed": 82,
      "wins": 55,
      "losses": 16,
      "otLosses": 11,
      "pointPct": 0.738,
      "goalDiff": 99,
      "goalsForPerGame": 3.68,
  ...

First 14 lines. Full response and every field

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 '{}'

Save the raw JSON

Keep your key in an environment variable so it never sits in a script or a chat, and write each response to a file:

bash
export PUCKAPI_API_KEY="your key here"

curl -s -X POST https://mcp.puckapi.com/v1/get_standings \
  -H "Content-Type: application/json" \
  -H "x-api-key: $PUCKAPI_API_KEY" \
  -d '{}' \
  -o get_standings.json

The file holds exactly what the API returned. Tools that page their results return a next_offset; send it back as offset for the next page.

ChatGPT and Claude

Both connect to the MCP server with a sign-in instead of a key: you sign in to PuckAPI once and press Allow. Step-by-step for ChatGPT and Claude.

Python

The official client is on PyPI. It has no required dependencies. Set PUCKAPI_API_KEY to your key and it is picked up automatically:

bash
pip install puckapi

Then call any endpoint as a method (the example uses pandas, pip install "puckapi[pandas]"):

python
from puckapi import Client, to_dataframe

client = Client()

odds = client.get_odds(game_id="2026020080", snapshot_type="closing")
df = to_dataframe(odds, key="odds")
print(df[["bookmaker", "mlHome", "mlAway", "total"]])
print("credits left:", client.last_credits_remaining)

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

Find the right call

All 31 questions

What timestamps mean, whether lines are pre-game, and what you can do with the data: data timing and rights.

Working Python, JavaScript and cURL for common questions, each run against the live API.

Endpoints

27 endpoints by category. Each page has parameters, requests in three formats, a full example response and every response field.

Multi-table10 credits/call

Reference

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 every month.

Base URL

text
https://mcp.puckapi.com

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

MCP: POST /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

Professional Women's Hockey League (PWHL)

PuckAPI also serves the PWHL. Pass "league": "pwhl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/pwhl. PWHL API coverage.

Ontario Hockey League (OHL)

PuckAPI also serves the OHL. Pass "league": "ohl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/ohl. OHL API coverage.

Western Hockey League (WHL)

PuckAPI also serves the WHL. Pass "league": "whl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/whl. WHL API coverage.

Quebec Maritimes Junior Hockey League (QMJHL)

PuckAPI also serves the QMJHL. Pass "league": "qmjhl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/qmjhl. QMJHL API coverage.

ECHL (ECHL)

PuckAPI also serves the ECHL. Pass "league": "echl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/echl. ECHL API coverage.

American Hockey League (AHL)

PuckAPI also serves the AHL. Pass "league": "ahl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/ahl. AHL API coverage.

United States Hockey League (USHL)

PuckAPI also serves the USHL. Pass "league": "ushl" to any tool that lists it, or connect to https://mcp.puckapi.com/mcp/ushl. USHL API coverage.

DataStatusCoverageVolume
Play-by-play
Every event, with rink coordinates, strength state, zone, shot type and the players involved where the event has them: goals, shots, misses, blocks, faceoffs, hits, giveaways, takeaways, penalties.
22,097 of 22,184 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,900,000+ events
Shift charts and situation time
Every player's shifts in every game, and from them the exact seconds each team spent at 5v5, on the power play, shorthanded or with the goalie pulled, plus each skater's time by strength. Game logs carry official time on ice and plus/minus.
22,009 of 22,237 completed games. The 228 gaps are preseason games for which the NHL publishes no shift chart or time-on-ice report. For 1,268 games the NHL's shift API has no chart, and the shifts come from its official HTML time-on-ice reports instead.
Available2010-11 through current16,000,000+ shifts
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,900+
Skaters
Skater season totals: goals, assists, points, plus/minus, power play and shorthanded production, shooting%, faceoff% and time on ice.
One line per player per regular season. A player traded mid-season is combined into one line; his faceoff% and time on ice are weighted by games played.
Available2010-11 to current14,000+
Goalies
Goalie stat lookup including save percentage, GAA, goals saved above expected, high-danger save%, rolling form and rest days.
AvailableSupported goalie stat seasons1,509
Teams
Team metadata, abbreviations, divisions, conferences, and arenas.
AvailableActive and historical franchises represented in PuckAPI34
Standings + rankings
Standings and rankings with 5v5 possession: Corsi%, Fenwick% and expected goals for and against.
Do not treat standings as real-time unless freshness is shown separately.
AvailableSupported seasons and current-season snapshots526
Odds
Odds for supported games, books, and markets where available.
Coverage varies by sportsbook, game, market, and source availability.
Partial2019 playoffs, then every game from 2019-20 through current191,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. Upcoming games carry lines up to a week ahead; until game day this is the latest morning line. From October 2026 each book's first posted line is also kept, as snapshot type "first".

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 All eight books (including DraftKings, FanDuel, BetMGM, theScore Bet and Pinnacle) fetched every hour from October 7 2026 for games in the next 7 days, with five labelled snapshots a day kept (latenight, earlyam, midday, afternoon, night) plus opening and closing; opening and closing history from the sportsbook odds archive covers seven books, among them DraftKings, FanDuel, BetMGM and Pinnacle, from 2020-21 and ESPN BET from 2023-24; 2019-20 to 2023-24 also carries Bet365, Caesars, Betfair, Unibet, PointsBet and others (closing lines). Sportsbook availability varies by game, market, and source. Do not assume every book is available for every game. Every game from 2019-20 has lines, plus 18 games of the 2019 playoffs; nothing earlier. Before 2023-24 the extra books (Bet365, Caesars, Betfair, Unibet and others) carry the closing line only; the sportsbook odds archive carries opening and closing lines for seven books, among them DraftKings, FanDuel, BetMGM and Pinnacle, from 2020-21 (ESPN BET from 2023-24).

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

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

Game IDs: Assigned 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.

Ready to start?

500 free credits every month. No credit card required.

Get a free key