← Plugin catalog
Data & Analytics

DunkAPI

DunkAPI v1.0.0

NBA basketball data and stats

Create a free account to save this plugin.

From the developer

Declared capabilities

  • Look up NBA, WNBA and college teams and players
  • Read standings, schedules and scores
  • Read box scores, leaders and team stats

Cost & access

DunkAPI does not sell anything through ChatGPT. The plugin is read-only: it has no checkout, purchase, subscription or credit top-up flow.

Declared limitations

  • Place a wager: wagering is not supported
  • Out of coverage: another sport
  • Account and billing change: not supported

Onboarding example

Show the 2024-25 NBA standings.
Sources & dates

Developer declarations; not independently tested. Listing last checked Nov 6, 2026. Package observed Nov 6, 2026.

View package source →

Description

From the marketplace listing

DunkAPI connects ChatGPT and Codex to NBA basketball data from DunkAPI. It covers the NBA since 2004 with every shot located, the WNBA since 2006, and Division I men's and women's college basketball. Ask for standings, schedules and scores, box scores, player averages and game logs, leaders, team ratings, play-by-play, shot charts, sportsbook odds, line movement and player prop lines. The plugin looks the answer up with read-only tools and reports what the data says, including the season, date and source of each number. The first time you use it, you sign in with your DunkAPI account. Limits: DunkAPI is read-only. It cannot place wagers, accept or track bets, or edit your account. Odds and prop lines are shown as information about the market, not as advice. Data comes from public sources and the DunkAPI pipeline and is not guaranteed to be error-free or current to the minute, so do not rely on it as the sole basis for financial decisions. Ratings shown are DunkAPI's own Elo-style ratings, not official rankings. Not affiliated with the NBA or any team. Bundled skills teach the model how to choose the right tool for a question and how to explain results.

Language: English · Automatically detected from descriptions.

Matches for “data layer”

Exact text from the indicated source. A mention alone does not establish support for your task.

Publisher description

DunkAPI brings NBA basketball data into ChatGPT and Codex with read-only tools and workflow skills: standings, schedules and scores, box scores, player averages and game logs, leaders, team ratings, play-by-play, shot charts, sportsbook odds, line movement and player prop lines. Sign in with your DunkAPI account.

Publisher full description

DunkAPI connects ChatGPT and Codex to NBA basketball data from DunkAPI. It covers the NBA since 2004 with every shot located, the WNBA since 2006, and Division I men's and women's college basketball. Ask for standings, schedules and scores, box scores, player averages and game logs, leaders, team ratings, play-by-play, shot charts, sportsbook odds, line movement and player prop lines. The plugin looks the answer up with read-only tools and reports what the data says, including the season, date and source of each number. The first time you use it, you sign in with your DunkAPI account. Limits: DunkAPI is read-only. It cannot place wagers, accept or track bets, or edit your account. Odds and prop lines are shown as information about the market, not as advice. Data comes from public sources and the DunkAPI pipeline and is not guaranteed to be error-free or current to the minute, so do not rely on it as the sole basis for financial decisions. Ratings shown are DunkAPI's own Elo-style ratings, not official rankings. Not affiliated with the NBA or any team. Bundled skills teach the model how to choose the right tool for a question and how to explain results.

Publisher subtitle

NBA basketball data and stats

Publisher capabilities · listing

Look up NBA, WNBA and college teams and players Read standings, schedules and scores Read box scores, leaders and team stats Read play-by-play and shot charts Read sportsbook odds and prop lines (information only)

Publisher keywords · listing

nba sports-data sports-analytics stats dunkapi

Changes

No changes recorded yet. Follow this plugin to keep track of future changes.

First seen Oct 30, 2026. Last seen Nov 6, 2026.

Keywords

Files & skills

File archives

Plugin package19 files · 85.5 KBBrowse files →
Skill instructions
dispatch4.54 KB

View saved version →

---
name: dispatch
description: "Routes a basketball analytics request to the right 2-3 skills. Load this FIRST when an NBA, WNBA or college basketball request comes in and you are unsure which skills to activate. Prevents loading all 16 skills when only 2-3 are needed. Do not use for a single obvious request such as devigging two prices, see odds-analysis directly."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Skill Dispatch Guide

Match the request to a pattern below, load those skills, and stop. Always load `dunkapi-tool` alongside any skill that needs data.

> **Default data tool:** DunkAPI (`dunkapi-tool`). A typical monthly allowance is 500 credits.

## When to Use

- A basketball request arrives and more than one skill could apply
- The user is new and does not know what to ask for
- A request spans data, modeling and market lines (for example "is Brunson's points line beatable?")

## When NOT to Use

- The request names one skill's job exactly ("devig these prices" goes straight to `odds-analysis`)
- The user wants a tool's parameters or cost, see `dunkapi-tool`

## Commands Available

None. This skill routes; `dunkapi-tool` makes the calls.

## First-Use Persona Detection

| Signal | Persona | Start with |
|--------|---------|-----------|
| "Who plays tonight?" "How did the Knicks do?" | Explorer | `game-lookup` + `team-analysis` |
| "Break down this player" "Compare these two" | Scout | `player-scouting` + `player-form` |
| "Where does he shoot from?" | Shot analyst | `shot-zone-analysis` |
| "What's the best price?" "How did the line move?" | Line shopper | `odds-explorer` |
| "Help me build a model" | Builder | `feature-engineering` + `walk-forward-validation` |
| "Does he go over his points line?" | Odds reader | `prop-modeling` + `player-form` |

## Request Patterns to Skills

### "Scores from last night" / "Who plays tonight" / "Find the Celtics-Heat game"
1. `game-lookup`
2. `dunkapi-tool`: `list_games`, `get_schedule`, `get_game`

### "Standings" / "Best team" / "Who plays fastest" / "Net rating"
1. `team-analysis`: standings, Elo, pace, four factors

### "Tell me about Jalen Brunson" / "Compare Tatum and Brown" / "Who led the league in true shooting"
1. `player-scouting`
2. If the question is about recent form: add `player-form`

### "Is he hot?" / "Last 10 games" / "Rolling average" / "Minutes trend"
1. `player-form`
2. `dunkapi-tool`: `get_player_games`

### "Where does he shoot?" / "Expected points" / "Best defence at the rim" / "Clutch shots"
1. `shot-zone-analysis`
2. `dunkapi-tool`: `get_shot_chart`, `get_plays`

### "What are the odds?" / "Best price" / "Line moved?" / "Sharp money?"
1. `odds-explorer`
2. For probability math: add `odds-analysis`

### "Preview tonight's Knicks game"
1. `game-preview` (it calls schedule, ratings, team stats, injuries and odds itself)
2. Add `team-analysis` if the user wants the efficiency detail

### "Devig these" / "What probability is -200 / +165?"
1. `odds-analysis`

### "Build a model" / "What features should I use?" / "Is my CV okay?"
1. `feature-engineering`
2. `walk-forward-validation`
3. `probability-calibration` once there are probabilities

### "Player props" / "Over/under on 24.5 points" / "Does he hit his line"
1. `prop-modeling`
2. `player-form` for the projection inputs
3. `dunkapi-tool`: `get_prop_history`, `get_player_props`

### "Women's college" / "WNBA" / "March Madness"
Same skills, pass `league`. Check `dunkapi-tool` for which tools support which league. Props exist for `nba`, `wnba`, `ncaam` only; `get_shot_chart` and `get_injuries` are NBA and WNBA only.

## Season Resolution

- `season` is the year the season ends. October 2026 to June 2027 is `2027`.
- The 2026-27 NBA regular season opens Oct 20, 2026. Before that, games in `get_schedule` are `preseason`, and `get_team_stats`, `get_ratings` and `get_standings` for the new season hold little or nothing. Preview the opener from `season: 2026` data plus the preseason schedule, and say so.
- 

Preview of the first 4,000 characters. Read full instructions →

dunkapi-tool6.96 KB

View saved version →

---
name: dunkapi-tool
description: "Default data source for the DunkAPI skills. Routes every call to the 18 DunkAPI tools for NBA, WNBA, men's and women's college basketball: games, box scores, play-by-play, shot charts, team ratings, odds, line movement and player props. Use when any other skill needs basketball data, or when the user asks which tool answers a question or what a call costs."
metadata:
  version: 1.0.0
  author: DunkAPI
  user-invocable: false
---

# DunkAPI Tool

> Connection: this plugin reaches the data through its MCP server, which the user connects with a normal OAuth sign-in. Never ask the user for an API key, token or password, and never put one in a tool argument.


Every other skill delegates data retrieval here. This skill owns the 18 tools, picks the cheapest call that answers the question, tracks credits, and explains the response envelope.

Full per-tool reference: https://dunkapi.com/docs. Live coverage by season: https://dunkapi.com/docs/atlas.

## Connecting

| Path | How |
|------|-----|
| Tool catalogue | `GET https://mcp.dunkapi.com/v1/tools` (JSON Schema for every tool) |



Over REST, every response is wrapped: `{"data": {...}}`. Read `response["data"]["standings"]`, not `response["standings"]`. REST responses carry `X-Credits-Used` and `X-Credits-Remaining` headers.

## Conventions every tool shares

- `league`: `nba` (default), `wnba`, `ncaam` (men's college), `ncaaw` (women's college). Not every tool accepts every league (table below).
- `season` is the year the season ends: `2026` = 2025-26, `2027` = 2026-27. WNBA seasons are the calendar year.
- `season_type`: `regular`, `postseason`, `play_in`, `preseason`.
- Dates are `YYYY-MM-DD` in US Eastern time.
- Game ids are ESPN game ids (strings like `"401859967"`). Player ids are ESPN athlete ids (like `"3934672"`). Teams take an id or an abbreviation (`NY`, `BOS`, `GS`, `SA`).
- Paged tools return `next_offset`; pass it back as `offset`.

## The 18 tools

| Tool | Credits | Leagues | Returns | Used by |
|------|---------|---------|---------|---------|
| `list_teams` | 1 | all | Team ids, abbreviations, conference | game-lookup, team-analysis |
| `search_players` | 1 | all | Player id from a name | player-scouting, player-form, prop-modeling |
| `get_schedule` | 2 | all | Next 1-30 days with the median line | game-preview, odds-explorer |
| `get_standings` | 2 | all | Standings computed from final games | team-analysis |
| `get_injuries` | 2 | nba, wnba | Status, injury type, expected return | game-preview, prop-modeling |
| `get_ratings` | 2 | all | DunkAPI Elo ratings, ranked | team-analysis, game-preview |
| `get_game` | 5 | all | Both box scores, every player line, each book's open and close, win probability range | game-lookup, game-preview |
| `get_player` | 5 | all | Profile, season averages and splits, last 10 games | player-scouting |
| `get_player_games` | 5 | all | A player's game log | player-form, prop-modeling |
| `get_leaders` | 5 | all | Season leaders by stat | player-scouting |
| `get_team_stats` | 5 | all | Pace, ratings, four factors, three-point rate | team-analysis, feature-engineering |
| `get_line_movement` | 10 | all | Snapshots of each book's line before tip-off | odds-explorer |
| `get_plays` | 10 | all | Play-by-play with shot x/y, zone, expected points, win probability | shot-zone-analysis |
| `get_shot_chart` | 10 | nba, wnba | Zone profile with expected points per shot | shot-zone-analysis |
| `get_player_props` | 10 (per game, see below) | nba, wnba, ncaam | Prop lines by book, opening or closing | prop-modeling |

`get_player_props` costs 10 credits for a whole game, or 10 credits per game returned when you pass `player_id` with `from_date` (up to 100 games). Pass `estimate_only: true` first to see the price without being charged.

## Tool selection guide

| You need | Use | Not |
|----------|-----|-----|
| Last night's scores | `list_games` with `date` | `get_game` per game |
| Tonight's games and spread 

Preview of the first 4,000 characters. Read full instructions →

feature-engineering9.39 KB

View saved version →

---
name: feature-engineering
description: "Builds leak-free features for basketball prediction models from DunkAPI data: rolling team margin and efficiency, Elo rebuilt game by game, rest days and back-to-backs, home court, opponent-adjusted form, market features and player minutes. Use when the user wants to build a model of game outcomes, margins, totals or player stats, or asks what features to use or whether a feature leaks. Do not use for choosing a validation scheme, see walk-forward-validation. Do not use for calibrating output probabilities, see probability-calibration. Do not use for descriptive team or player summaries, see team-analysis or player-form."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Feature Engineering

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> Cheapest feature source: `list_games` (2 credits per page of up to 50 games). Box-score features need `get_game` (5 credits per game) or `get_player_games` (5 per player-season).

A basketball model fails in one of two ways: the features contain the future, or they contain nothing the market does not already know. This skill is about the first problem and honest about the second.

## When to Use

- "What features should I use to predict NBA margins?"
- "Build me rolling team ratings that don't leak"
- "Is using `get_team_stats` for a backtest okay?" (usually no, see below)
- Setting up a training table for game, total or player-stat models

## When NOT to Use

- Splitting data for validation, see `walk-forward-validation`
- Making probabilities trustworthy, see `probability-calibration`
- Describing a team or player without building a model, see `team-analysis`, `player-form`

## Commands Available

| Command | What it gives a feature table | Credits |
|---------|-------------------------------|---------|
| `list_games` | Date, teams, scores, overtime, season type, neutral site: enough for margin, rest, Elo | 2 per page |
| `get_game` | Team box scores (possessions, four factors) and each book's open and close | 5 per game |
| `get_player_games` | Player-level minutes and lines for availability and role features | 5 per player-season |
| `get_odds` | Opening and closing lines per book; `date` returns a whole day for 10 | 5 / 10 |
| `get_injuries` | Current availability only (not a historical archive by default) | 2 |
| `get_team_stats`, `get_ratings`, `get_standings` | Season-level summaries: do not use as pre-game features for past games | 5 / 2 / 2 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_features`, `get_training_data` | Build from `list_games` and `get_game` |
| `get_historical_ratings` (as of a past date) | Rebuild Elo from `list_games` (below) |
| `get_historical_injuries` by game | `get_injuries` accepts a `date`, one report per call; archive it going forward |
| `get_lineups`, `get_tracking` | Not served |

## The Rule: As-Of Features Only

A feature for game N may use only information available before tip-off of game N.

| Source | Safe for past games? | Why |
|--------|---------------------|-----|
| `list_games` rolled with `shift(1)` | Yes | Built from earlier games only |
| `get_team_stats {"season": 2025}` for a 2024-25 game | No | Whole-season average includes the game and every game after it |
| `get_ratings` end-of-season Elo | No | Includes later games; also regresses at season boundaries |
| `get_standings` | No | Final standings |
| `get_player` season averages | No | Same as team stats |
| Closing line | At tip only | Use opening for earlier decisions |
| Opening line (`*_open`) | Yes if you act at open | Check `captured_at` |

If the model scores well with season-level inputs and badly with as-of ones, the first score was leakage.

## How It Works

**Step 1: Build the game table.** Page `list_games` for the seasons you want (oldest first after sorting). Keep `date`, home and away ids, scores, `overtime_periods`, `season_type`, `neutral_site`. Drop preseason; d

Preview of the first 4,000 characters. Read full instructions →

game-lookup6.55 KB

View saved version →

---
name: game-lookup
description: "Finds basketball games and reads results: scores by date, team, range or season, upcoming schedule, and a single game's full box score. Use when the user asks who played, what the score was, who plays tonight, a team's recent results, or wants a game id for another call. Covers NBA, WNBA, men's and women's college. Do not use for odds comparison, see odds-explorer. Do not use for team strength, see team-analysis. Do not use for a pre-game breakdown, see game-preview."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Game Lookup

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `list_games` (2 credits) for results, `get_schedule` (2) for upcoming games, `get_game` (5) for one game in full.

You find the right game fast and return it cleanly. Most other skills need a `game_id` first; this one produces it.

## When to Use

- "What was the score of the Knicks game?" / "Last night's NBA results"
- "Who plays tonight?" / "Celtics schedule this week"
- "Show me the box score for that game"
- "Every Lakers road game this season"
- Any request that needs a `game_id` before another skill can run

## When NOT to Use

- Comparing sportsbooks or reading line moves, see `odds-explorer`
- Ranking teams or reading efficiency, see `team-analysis`
- A full matchup breakdown with injuries and ratings, see `game-preview`
- Shot-level detail from a game, see `shot-zone-analysis`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `list_teams` | Team ids and abbreviations for a season | 1 |
| `list_games` | Games with scores by season, date, range or team, newest first | 2 |
| `get_schedule` | Next 1-30 days with the median spread, total and moneylines | 2 |
| `get_game` | One game: team box scores, every player line, each book's open and close, win-probability range | 5 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_box_score` | `get_game` |
| `get_scoreboard` | `list_games` with `date` (finals) or `get_schedule` (upcoming) |
| `get_live_scores` | None. Data is historical and next-day, not live |
| `get_head_to_head` | `list_games` with `team`, then filter the opponent in code |

## Season Resolution

- `season` is the year the season ends: 2025-26 is `2026`, 2026-27 is `2027`.
- Oct 20, 2026 is the NBA opener. Before it, `get_schedule` returns `preseason` games tagged `season: 2027`.
- WNBA is the calendar year. `season_type` values: `regular`, `postseason`, `play_in`, `preseason`.
- Dates are US Eastern. A 10:30 pm ET tip can have a UTC `starts_at` on the next day; filter by the `date` field, not `starts_at`.

## How It Works

**Step 1: Resolve the team.** If the user says "the Knicks" and you do not have the abbreviation, call `list_teams` (1 credit). The API accepts an id or an abbreviation (`NY`, `BOS`, `GS`, `SA`). Do not guess; `GS` and `NY` are the codes here, not `GSW` or `NYK`.

**Step 2: Pick the listing call.**

| Question | Call |
|----------|------|
| Last night's scores | `list_games` with `date` set to yesterday |
| A team's recent games | `list_games` with `team` and `limit` |
| A playoff series | `list_games` with `team`, `season`, `season_type: "postseason"` |
| A date range | `list_games` with `from` and `to` |
| Tonight and the week | `get_schedule` with `days` and optionally `team` |

**Step 3: Get the box score only when needed.** `list_games` already has the score, venue and overtime count. Call `get_game` (5 credits) for player lines, team box scores, books' lines or the win-probability range.

**Step 4: Present it.** Lead with the answer (score, winner, margin), then the detail.

### Live example

`list_games {"team": "NY", "season": 2026, "limit": 3}` returned the latest postseason games (NY vs SA, June 2026), newest first. Trimmed:

```json
{"data": {"games": [
  {"game_id": "401859967", "season": 2026, "season_type": "postseason",
   "date": "2026-06-13", "status": "final",

Preview of the first 4,000 characters. Read full instructions →

game-preview7.28 KB

View saved version →

---
name: game-preview
description: "Builds a full pre-game basketball preview: teams' Elo and efficiency, recent form, rest and back-to-backs, injuries, the market line across books, and a simple projection with its uncertainty. Use when the user asks to preview or break down tonight's game or the season opener, or wants everything needed before tip in one place. Works for the new season before it has games (falls back to last season's numbers and says so). Covers NBA, WNBA, men's and women's college. Do not use for results after the fact, see game-lookup. Do not use for devigging, see odds-analysis."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Game Preview

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> A full preview costs about 20 credits: `get_schedule` (2), `get_ratings` (2), `get_team_stats` (5), `get_injuries` (2), `get_odds` (5), and two `list_games` calls (2 each) for form and rest.

A compound skill: it calls several tools in a fixed order and assembles one page. The point is a number you can defend and the list of things that would change it.

## When to Use

- "Preview tonight's Knicks game" / "Break down the opener"
- "What do I need to know before Celtics-Heat?"

## When NOT to Use

- Final scores and box scores, see `game-lookup`
- Only prices and movement, see `odds-explorer`
- Only team strength, see `team-analysis`

## Commands Available

| Command | Use in a preview | Credits |
|---------|------------------|---------|
| `get_schedule` | Find the `game_id`, tip time, venue and the median line | 2 |
| `get_ratings` | Elo for both teams | 2 |
| `get_team_stats` | Pace, ratings and four factors (all teams in one call, or one with `team`) | 5 |
| `get_injuries` | Who is out or day-to-day (NBA and WNBA only) | 2 |
| `list_games` | Each team's last 10 results and the dates for rest | 2 each |
| `get_odds` | Every book's line for the game | 5 |
| `get_line_movement` | Optional: how the line has moved | 10 |
| `get_player` | Optional: a key player's last 10 games | 5 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_game_preview`, `get_matchup` | This skill assembles it |
| `get_lineups`, `get_starting_five` | Not served. Infer likely starters from the last box score via `get_game` |
| `get_referee_assignments` | Not served |
| `get_head_to_head` | `list_games` with `team`, filter the opponent |

## Season Resolution (important for the opener)

The 2026-27 NBA regular season opens Oct 20, 2026. Before that:

- `get_schedule` shows preseason games with `season: 2027` and often only one book's spread and total.
- `get_ratings` and `get_team_stats` for `season: 2027` have little or nothing. Use `season: 2026` and label every number "2025-26". Elo regresses a quarter of the way toward 1500 between seasons per the API's method note, so last season's end-of-year rating overstates how far apart teams are.
- Preseason box scores are a poor guide to rotations: starters play limited minutes. Do not fold preseason results into form.
- After about 15 games per team, switch to `season: 2027` and drop the carryover caveat.

## How It Works

**Step 1: Find the game.** `get_schedule {"days": 3, "team": "NY"}`. Take `game_id`, `home.abbrev`, `away.abbrev`, `starts_at` and `line` (`home_spread`, `total`, `home_ml`, `books`).

**Step 2: Strength.** `get_ratings {"season": 2026}` gives Elo for every team. The rating gap `d = rHome - rAway + home_edge`. Home edge is not published as a parameter; use about 60 to 100 points and say it is an assumption. Win probability `= 1 / (1 + 10^(-d/400))`. The API's own anchor: a 100-point gap is about a 64% favourite on a neutral floor.

**Step 3: Efficiency.** `get_team_stats {"season": 2026}` (all teams, 5 credits). Pull `pace`, `off_rating`, `def_rating`, `net_rating`, `efg_pct`, `tov_pct`, `oreb_pct`, `ft_rate`, `three_rate` for both teams. Projected margin (home minus away, neutral):

```
home_pts = (home.off_rating + away.def

Preview of the first 4,000 characters. Read full instructions →

odds-analysis6.73 KB

View saved version →

---
name: odds-analysis
description: "Odds math for basketball betting markets: American, decimal and implied probability conversion, vig, and four devigging methods (multiplicative, additive/Shin, power) applied to moneylines, spreads, totals and player props, plus building a consensus no-vig line across sportsbooks. Use when the user asks what a price implies, how to remove the vig, what the true probability is, or what a fair line is. Do not use for finding the best price or line movement, see odds-explorer."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Odds Analysis

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_odds` (5 credits per game) for moneylines, spreads and totals with prices. `get_player_props` (10) for prop prices. The math itself is local.

Prices are not probabilities. A book's two sides add to more than 100%; the excess is its margin. Removing it gives the market's own view, which is the benchmark every edge claim has to beat.

## When to Use

- "What probability does -195 imply?"
- "Devig this moneyline: -200 / +165"
- "What is the fair total if over is -108 and under is -112?"
- "What's the no-vig line across all books?"

## When NOT to Use

- Hunting the best number or reading line moves, see `odds-explorer`

## Commands Available

| Command | Role | Credits |
|---------|------|---------|
| `get_odds` | Per-book prices and closing implied probabilities | 5 per game, 10 per date |
| `get_player_props` | Over and under prices for props | 10 |
| `get_schedule` | Median line and `home_implied_prob` on upcoming games | 2 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_no_vig_odds`, `get_fair_odds` | Compute locally with the methods below |
| `get_true_probability` | Same |

## Conversions

```
American to implied probability:
  odds > 0:  p = 100 / (odds + 100)
  odds < 0:  p = -odds / (-odds + 100)
Decimal odds = 1 / p        (American +165 = 2.65; -195 = 1.513)
American from p:
  p < 0.5:   odds = +100 * (1 - p) / p
  p >= 0.5:  odds = -100 * p / (1 - p)
Payout per 1 unit staked at American odds o:
  o > 0: o/100       o < 0: 100/(-o)
```

The API returns `home_close_prob` and `away_close_prob` on `get_odds` rows: those are the raw implied probabilities of the closing moneyline (they sum above 1). Treat them as inputs to devigging, not as the answer.

## Vig

`overround = pA + pB - 1`. A -110/-110 spread is 4.76%. Sharper books run lower. In the live row set below, raw sums ranged from 1.019 (ESPN BET) to 1.044 (BetMGM) on one game's moneyline.

## Devigging Methods

Given two raw probabilities `a` and `b` with `a + b = S > 1`:

| Method | Formula | Behaviour |
|--------|---------|-----------|
| Multiplicative (proportional) | `a/S`, `b/S` | Simple default. Spreads the margin proportionally |
| Additive | `a - (S-1)/2`, `b - (S-1)/2` | Equal cut from each side. Can push a longshot too low, so check it stays positive |
| Shin | Solves for an insider-trading fraction `z` | Shifts more of the margin onto longshots. For a two-way market it equals the additive result |
| Power | Find `k` so `a^k + b^k = 1`; use `a^k`, `b^k` | Takes relatively more off the longshot, which matches the favourite-longshot bias often seen in betting markets |

### Worked example with live numbers

`get_odds {"game_id": "401859967"}` returned Pinnacle's closing moneyline as SA (home) -195, NY (away) +173. Raw: `0.6610 + 0.3663 = 1.0273` (2.73% margin).

| Method | Home (SA) | Away (NY) |
|--------|----------:|----------:|
| Raw | 0.6610 | 0.3663 |
| Multiplicative | 0.6434 | 0.3566 |
| Additive / Shin | 0.6474 | 0.3526 |
| Power (k = 1.043) | 0.6493 | 0.3507 |

The methods differ by less than 1 point on a favourite priced near 65%, so for NBA sides the choice rarely changes a decision. The spread widens as the favourite gets shorter (-600 or more), where power and Shin cut the longshot harder. Pick one and keep it for the whole analysis; mixing methods inside on

Preview of the first 4,000 characters. Read full instructions →

odds-explorer8.21 KB

View saved version →

---
name: odds-explorer
description: "Multi-book basketball odds comparison: best moneyline, spread and total across sportsbooks, vig per book, opening versus closing lines, and pre-tip line movement. Use when the user asks for current or historical odds, the best price, which book is off the market, how a line moved, or whether the home side covered. Covers NBA, WNBA, men's and women's college. Do not use for devigging or probability math, see odds-analysis. Do not use for player props, see prop-modeling."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Odds Explorer

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_schedule` (2 credits) for the median line on upcoming games, `get_odds` (5 per game, 10 per date) for every book, `get_line_movement` (10 per game) for snapshots before tip-off.

You find the best available price, show what each book charges, and read line movement without overstating what snapshots can prove.

## When to Use

- "Best spread on Knicks-Spurs?" / "Which book has the highest total?"
- "What were the closing lines for last night's slate?"
- "Did the home team cover?" / "Did it go over?"
- "How did the line move before tip?"
- Reading the market before a game preview or a bet

## When NOT to Use

- Converting prices to true probabilities, see `odds-analysis`
- Player prop lines, see `prop-modeling`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `get_schedule` | Upcoming games with the median spread, total and moneylines across posted books | 2 |
| `get_odds` | Every book's moneyline, spread and total, opening and closing, with results against the median close. `game_id` for one game, `date` for a day | 5 per game, 10 per date |
| `get_line_movement` | Snapshots of each book's moneyline, spread and total before tip-off. Optional `provider` | 10 |
| `get_game` | Box score plus each book's open and close (use when you want both) | 5 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_live_odds` | None. Lines are pre-game; `get_schedule` shows what is posted |
| `get_best_book` | Compute from `get_odds` rows |
| `get_public_betting` | Not served. Do not infer public percentages |
| `get_closing_line` | Closing fields (`*_close`) on `get_odds` rows |
| `get_alt_lines` | Not served; one spread and one total per book |

## Coverage and What a Line Is

- Per-book moneyline, spread and total with opening and closing values. Opening and closing per book come from The Odds API from July 2020 and from ESPN from 2023-24; before that, only ESPN's final line. Check https://dunkapi.com/docs/atlas for coverage by season and league before promising history.
- Women's college lines start November 2024, with fewer books.
- Pre-game snapshots: ESPN's once a day, The Odds API's every hour for games in the next two days. That sets the resolution of `get_line_movement`: you can see a half-point move across hours or days, not a 90-second steam move.
- Books appear under their display names in `get_odds` and `get_line_movement` (`DraftKings`, `FanDuel`, `ESPN BET`, `Pinnacle`, `BetMGM`, `Bovada`, `BetOnline`, `MyBookie` in the live call below). Prop calls use lowercase keys (`draftkings`); do not mix them.
- Preseason games can have one book and no moneyline. Say so; one book is not a market.

## Season Resolution

For games before the Oct 20, 2026 opener, `get_schedule` returns preseason games with `season: 2027`. Use `get_schedule` for lines on future games and `get_odds` for lines on games already played or about to be.

## How It Works

**Step 1: Identify the game.** Use `get_schedule {"days": 3, "team": "NY"}` or `list_games` (see `game-lookup`). Do not pull odds for a guessed id.

**Step 2: Pull every book.** One game: `get_odds {"game_id": "401859967"}`. A whole day, 10 flat: `get_odds {"date": "2026-06-13"}`. For three or more games the date form is cheaper.

**Step 3: Read the columns.** Each `books` ro

Preview of the first 4,000 characters. Read full instructions →

player-form7.92 KB

View saved version →

---
name: player-form
description: "Reads a basketball player's recent form from his game log: rolling averages, minutes trend, per-minute rates, rest effects, home and road splits and opponent context, with proper shrinkage so a hot week is not mistaken for a new talent level. Use when the user asks if a player is hot, how his minutes have changed, what his last 10 games say, or needs rolling inputs for a projection. Covers NBA, WNBA, men's and women's college. Do not use for season profile and comparisons, see player-scouting. Do not use for shot location, see shot-zone-analysis. Do not use for prop lines, see prop-modeling."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Player Form

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_player_games` (5 credits for a season's log, paged by `limit` and `offset`). `get_player` (5) already contains the last 10 games if that is all you need.

Recent form is mostly minutes and role, a little shooting luck, and very little "heat". This skill separates them.

## When to Use

- "Is Tatum hot?" / "What has his minutes done since the trade?"
- "Give me his last 10 and last 20"
- Rolling inputs for a points, rebounds or assists projection
- Checking whether a big night was role-driven or shooting-driven
- Home/road, rest and opponent splits

## When NOT to Use

- Season averages and cross-player comparisons, see `player-scouting`
- Where the shots came from, see `shot-zone-analysis`
- Turning a projection into a bet against a line, see `prop-modeling`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `search_players` | Player id from a name | 1 |
| `get_player_games` | Full game log, newest first: opponent, home, result, minutes, box score line. Filters `season`, `season_type`, `limit`, `offset` | 5 |
| `get_player` | Profile, season rows, last 10 games | 5 |
| `list_games` | Team schedule dates, for rest and team context | 2 |
| `get_game` | One game's full lines (when you need teammates' minutes) | 5 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_player_stats` | `get_player_games` or `get_player` |
| `get_hot_players`, `get_trending` | Compute from the game log |
| `get_player_splits` | Group the log yourself |
| `get_minutes_projection`, `get_lineups` | Not served; model minutes from the log |
| `get_usage_rate` | Not served; use `fga + 0.44 * fta + tov` per minute as a usage proxy |

## Season Resolution

`season` is the year the season ends (2025-26 is `2026`). The default is the latest season. In October of a new season the log holds only preseason games; filter on `season_type` before reading anything into them. In game-log rows `season_type` is returned as a number (3 appeared on postseason games); in `list_games` it is a string. Request the type you want with the string parameter and do not rely on the numeric code for anything else.

## How It Works

**Step 1: Pull the log.** `get_player_games {"player_id": "3934672", "season": 2026, "limit": 100}` returns newest first. Each row: `game_id date season season_type opponent home result starter did_not_play minutes pts fgm fga tpm tpa ftm fta oreb dreb reb ast stl blk tov pf plus_minus`.

```json
{"date": "2026-06-13", "opponent": "SA", "home": false, "result": "W",
 "starter": true, "minutes": 41, "pts": 45, "fgm": 14, "fga": 27,
 "tpm": 4, "tpa": 7, "ftm": 13, "fta": 15, "reb": 3, "ast": 3, "tov": 3}
```

**Step 2: Clean.** Reverse to oldest-first. Drop `did_not_play` rows from rate stats but keep them as a count (availability is itself information). Mark blowouts if you have the score (from `list_games`): minutes in a 25-point game are not minutes in a close one.

**Step 3: Minutes first.** Compute a rolling mean of `minutes` over 5 and 10 games, and the share of games under 30. Most "hot" and "cold" stretches are minutes moving.

**Step 4: Rates.** Per-36 and per-minute rates are steadier than counts:

```pytho

Preview of the first 4,000 characters. Read full instructions →

player-scouting6.94 KB

View saved version →

---
name: player-scouting
description: "Looks up and profiles basketball players: finds the player id, reads per-season averages and shooting splits, compares two or more players on a per-minute basis, and pulls season leaderboards. Use when the user asks about a player, who leads a stat, how two players compare, or whether a scoring line is efficient or lucky. Covers NBA, WNBA, men's and women's college. Do not use for rolling or recent form across a season, see player-form. Do not use for shot location, see shot-zone-analysis. Do not use for prop lines, see prop-modeling."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Player Scouting

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `search_players` (1 credit) to get the id, `get_player` (5) for profile and averages, `get_leaders` (5) for leaderboards.

You turn a name into a defensible read on a player: usage-adjusted, efficiency-checked, with the sample size stated.

## When to Use

- "Tell me about Jalen Brunson" / "Is he actually efficient?"
- "Compare Tatum and Brown" / "Who is the better rebounder per minute?"
- "Who led the league in true shooting?" / "Top 10 in assists"
- "How did he do in the playoffs vs the regular season?"
- Finding a `player_id` for another skill

## When NOT to Use

- Game-by-game rolling averages or minutes trends, see `player-form`
- Where a player shoots from, see `shot-zone-analysis`
- Whether he will beat a points line, see `prop-modeling`
- A team-level question, see `team-analysis`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `search_players` | Player id from a full or partial name, most recent players first | 1 |
| `get_player` | Profile, per-season averages and shooting splits (regular season and postseason as separate rows), last 10 games | 5 |
| `get_leaders` | Season leaders by `pts reb ast stl blk tpm min plus_minus fg_pct tp_pct ft_pct ts_pct total_pts` | 5 |
| `get_player_games` | Full game log (for form, see `player-form`) | 5 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_player_stats` | `get_player` |
| `get_usage_rate`, `get_per`, `get_bpm`, `get_vorp` | Not served. Compute per-minute rates and true shooting from `get_player` fields |
| `get_player_tracking` | Not served; no speed, touches or contested-shot data |
| `compare_players` | Call `get_player` for each, compare in code |
| `get_draft_prospects`, `get_contract` | Not served |

## Season Resolution

`season` is the year the season ends (2025-26 is `2026`). The WNBA uses the calendar year. `search_players` returns `last_season`; a stale value means the player is retired or has not played recently.

## How It Works

**Step 1: Find the id.** `search_players {"name": "brunson", "limit": 3}` returned two people:

```json
{"data": {"players": [
  {"player_id": "3934672", "name": "Jalen Brunson", "position": "G", "team": "NY", "last_season": 2027},
  {"player_id": "106", "name": "Rick Brunson", "position": "PG", "team": "PHI", "last_season": 2007}
]}}
```

Match on `last_season` and `team` before spending 5 credits on the wrong profile. Pass `league` for WNBA or college; the default is the NBA.

**Step 2: Pull the profile.** `get_player` returns `player`, `seasons` (one row per season per `season_type`, with `games starts min pts reb ast stl blk tov oreb dreb pf plus_minus fgm fga tpm tpa ftm fta fg_pct tp_pct ft_pct efg_pct ts_pct`) and `recent_games` (last 10).

**Step 3: Normalize.** Per-game numbers hide minutes. Convert before comparing:

```
per36(stat)   = stat / min * 36
fga_per36     = fga/games / min * 36
ts_pct        = pts / (2 * (fga + 0.44 * fta))          [totals, not per game]
three_rate    = tpa / fga
ft_rate       = fta / fga
ast_to_tov    = ast / tov
```

`total_pts`, `fgm`, `fga` and the other counting fields on a season row are season totals; `pts`, `reb`, `ast` and `min` are per-game averages. Do not divide a total by a per-game numbe

Preview of the first 4,000 characters. Read full instructions →

probability-calibration7.17 KB

View saved version →

---
name: probability-calibration
description: "Checks and fixes whether basketball model probabilities mean what they say: reliability tables, Brier score and log loss, Platt scaling and isotonic regression fitted out of sample, converting predicted margins to win and cover probabilities, and shrinking toward the market. Use when a model outputs win, cover or over probabilities, asks if 65% really wins 65% of the time, or needs probabilities from a margin model. Do not use for building the model, see feature-engineering. Do not use for choosing splits, see walk-forward-validation."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Probability Calibration

> **Default data tool:** DunkAPI (`dunkapi-tool`) only for outcomes and the market benchmark: `list_games` (2 credits per page), `get_odds` (`result.home_covered`, `result.over`). Calibration itself is local.

Every number built on a probability inherits its error. An uncalibrated 70% that is really 60% turns a small edge into a negative one.

## When to Use

- "My model says 68% for the Knicks. Can I trust that?"
- "Is Platt scaling or isotonic better here?"
- "How do I turn a predicted margin into a win probability?"

## When NOT to Use

- Fitting the model itself, see `feature-engineering`
- Time-ordered evaluation design, see `walk-forward-validation`

## Commands Available

| Command | Role | Credits |
|---------|------|---------|
| `list_games` | Final scores to label outcomes | 2 per page |
| `get_odds` | Market probability to benchmark (and `home_covered`, `over` to label cover and total outcomes) | 5 per game, 10 per date |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_calibration`, `get_model_probabilities` | Compute locally from your own predictions |

## What Calibrated Means

Among all games where the model said about 70%, the home side should win about 70% of them. Two separate qualities:

- **Calibration:** do stated probabilities match frequencies?
- **Discrimination (sharpness):** does the model separate likely from unlikely outcomes?

A model that always says 58% for the home team in a league where home teams win 58% is calibrated and useless. You need both.

## How It Works

**Step 1: Use out-of-sample predictions only.** Generate predictions with `walk-forward-validation`. Calibrating on training predictions measures overfit, not reliability.

**Step 2: Reliability table.** Bin predictions (deciles, or equal-count bins), and compare the mean prediction to the observed rate.

```python
import numpy as np, pandas as pd
df["bin"] = pd.qcut(df.p, 10, duplicates="drop")
rel = df.groupby("bin").agg(pred=("p","mean"), obs=("y","mean"), n=("y","size"))
rel["se"] = np.sqrt(rel.obs * (1 - rel.obs) / rel.n)
```

Read it with the standard error: a bin of 120 games has a standard error near 4.5 points, so a 3-point miss is noise. Plot `obs` against `pred` with error bars; the diagonal is perfect.

**Step 3: Scores.**

| Metric | Formula | Notes |
|--------|---------|-------|
| Log loss | `-mean(y*log(p) + (1-y)*log(1-p))` | Coin flip 0.693; punishes overconfidence |
| Brier | `mean((p - y)^2)` | Coin flip 0.25 |
| Calibration slope | Logistic regression of `y` on `logit(p)` | 1.0 ideal; below 1 means overconfident |
| Calibration intercept | Same regression | 0 ideal |

Brier decomposes into reliability (bad) minus resolution (good) plus uncertainty (fixed). Improve reliability by calibrating; improve resolution only with better features.

**Step 4: Choose a correction.**

| Method | Use when | Risk |
|--------|----------|------|
| Platt (logistic on the score) | Under about 3,000 calibration games | Assumes a sigmoid shape |
| Isotonic regression | 3,000+ calibration games | Steps; overfits small samples |
| Shrink toward the market: `p' = w*p_model + (1-w)*p_market` | Model has some edge but is overconfident | Needs a devigged market probability (see `odds-analysis`) |

NBA seasons are small. One season is a

Preview of the first 4,000 characters. Read full instructions →

prop-modeling9.01 KB

View saved version →

---
name: prop-modeling
description: "Builds basketball player prop models for points, rebounds, assists, threes, points + rebounds + assists, blocks and steals: projects minutes and per-minute rates from the game log, turns a projection into an over/under probability with a suitable distribution, compares it with devigged prop prices across books, and checks a player's history against his lines. Use when the user asks if a player will go over a number, how often he has hit his line, what a fair prop price is, or how to project a stat line. Props exist for NBA, WNBA and men's college only. Do not use for team-side or total models, see feature-engineering. Do not use for recent-form description alone, see player-form."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Prop Modeling

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_prop_history` (10 credits for up to 200 games) shows each game's closing line against what happened. `get_player_props` (10 credits for a whole game, or 10 per game for one player across dates) gives every book's price. `get_player_games` (5) feeds the projection.

A prop is a single player-game outcome with a wide spread. The line already contains minutes, matchup and injuries. The only way to add value is to model one of those better than the market, and to know when you have not.

## When to Use

- "Will Brunson go over 24.5 points?"
- "How often has he hit his points line this season?"
- "Which book has the best price on his rebounds over?"
- "Project his points, rebounds and assists for tonight"
- Checking whether a player's line has been set too high or low historically

## When NOT to Use

- Team sides and totals, see `feature-engineering`, `odds-analysis`
- Descriptive form with no line involved, see `player-form`
- Women's college basketball: no player props are served for `ncaaw`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `get_prop_history` | One market for one player: per game the closing line (median across books or one `bookmaker`), opening line, prices, `actual`, `result`, `margin`, and a `summary` with `over_rate`. Returns up to 200 games | 10 |
| `get_player_props` | Props by book for a game (`game_id`), or one player across dates (`player_id` + `from_date`, optional `to_date`). `market`, `bookmaker`, `snapshot_type` (`closing` default, or `opening`). `estimate_only` returns the cost without charging | 10 per game |
| `search_players` | Player id | 1 |
| `get_player_games` | Game log for minutes and rates | 5 |
| `get_injuries` | Availability of the player and his teammates | 2 |
| `get_odds` | Game spread and total (blowout risk, pace) | 5 |

Markets: `player_points`, `player_rebounds`, `player_assists`, `player_threes`, `player_points_rebounds_assists`, `player_blocks`, `player_steals`. Leagues: `nba`, `wnba`, `ncaam`.

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_prop_projections`, `get_dfs_projections` | Build locally |
| `get_alt_lines` | Not served; one line per book per snapshot |
| `get_live_props` | Not served; closing or opening snapshots only |
| `get_lineups`, `get_minutes_projection` | Model minutes from the log |
| Props for `ncaaw` | Not available |

## Coverage

Prop lines run from May 2023 for the NBA and WNBA and from the 2023-24 season for men's college. Prices come from several books (DraftKings, FanDuel, BetMGM, ESPN BET, Pinnacle and others). `get_player_props` returns lowercase bookmaker keys (`draftkings`, `betmgm`, `espnbet`); `get_odds` returns display names. Use the right form per tool.

## How It Works

**Step 1: Establish the base rate from history.** `get_prop_history {"player_id": "3934672", "market": "player_points", "from_date": "2025-10-20", "limit": 6}` returned six games. Trimmed:

```json
{"data": {"games": [
  {"game_date": "2025-10-22", "line": 24.5, "open_line": 24.5, "over_odds": -106, "under_odds": -120, "books": 7, "actua

Preview of the first 4,000 characters. Read full instructions →

shot-zone-analysis8.32 KB

View saved version →

---
name: shot-zone-analysis
description: "Analyzes basketball shot profiles by zone using DunkAPI shot data: attempts, makes and points per shot in restricted area, paint, midrange, corner three and above-the-break three, compared with expected points per shot to separate shot quality from shot making. Also covers team defence by zone, clutch shots and drawing a shot chart from x/y. Use when the user asks where a player or team shoots, whether a hot shooter is lucky, which defence gives up the worst shots, or wants expected points. Do not use for season box-score averages, see player-scouting. Do not use for team pace and ratings, see team-analysis."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Shot Zone Analysis

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_shot_chart` (10 credits) for zone summaries, `get_plays` (10) for individual shots with game context.

The question is rarely "what is his FG%". It is: where do the shots come from, what is each shot worth on average, and is the result above or below what those shots usually produce.

## When to Use

- "Where does Brunson score from?" / "Does he live in the midrange?"
- "Is his shooting sustainable?" (shot quality versus shot making)
- "Which team allows the most corner threes?" (defence by zone)
- "Show his clutch shots" / "Every shot he took in the 4th"
- "Draw me a shot chart"

## When NOT to Use

- Season averages and per-36 rates, see `player-scouting`
- Team pace, ratings and four factors, see `team-analysis`
- Game-by-game minutes and scoring trend, see `player-form`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `get_shot_chart` | Zone table (`attempts made pct points_per_shot expected_points_per_shot`) and a `share` of attempts for a player, a team, a team's opponents (`opponent: true`), or one game. `include_shots: true` adds each shot's x, y, result (up to 3,000). NBA and WNBA only | 10 |
| `get_plays` | Play-by-play with `shot` objects: `made points_attempted x y distance_ft zone expected_points`, plus score and home win probability. Filter by `zone`, `period`, `made`, `clutch`, `shots_only`. All four leagues | 10 |
| `search_players` | Find the player id | 1 |
| `list_teams` | Team abbreviations | 1 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_shot_quality`, `get_xpts` | Fields on `get_shot_chart` and `get_plays` |
| `get_defender_distance`, `get_shot_tracking` | Not served; no contest or tracking data |
| `get_league_shot_averages` | Not served; build a baseline by calling `get_shot_chart` per team |
| College `get_shot_chart` | Not available for `ncaam` or `ncaaw`; use `get_plays` and check the `shot` fields are populated before relying on zones |

## Zones

`restricted_area`, `paint` (non-restricted), `midrange`, `corner_3`, `above_break_3`, `free_throw`. The free throw row has `expected_points_per_shot: null` and no x/y; `share` and `field_goal_attempts` cover field goals only.

Play-by-play covers NBA games back to 2003-04, and the `get_plays` tool description says win probability after each play is available from 2018. Check https://dunkapi.com/docs/atlas for the seasons that carry shot locations before building a multi-year study.

## How It Works

**Step 1: Pull the profile.** `get_shot_chart {"player_id": "3934672", "season": 2026}`.

**Step 2: Read quality and result separately.**

- `expected_points_per_shot` (xPPS) is what the shot is worth on average given where and how it was taken.
- `points_per_shot` (PPS) is what the player actually scored: `pct * 2` or `pct * 3`.
- Shot making = `PPS - xPPS` per zone.
- Points above expected = `sum(attempts * (PPS - xPPS))` over field-goal zones.

The same zone has different xPPS for different players (restricted area read 1.27 for Jayson Tatum in 2024 and 1.132 for Brunson in 2026), so xPPS reflects shot location and type within the zone, not a single zone constant. Compare a p

Preview of the first 4,000 characters. Read full instructions →

team-analysis7.96 KB

View saved version →

---
name: team-analysis
description: "Evaluates basketball teams: standings, DunkAPI Elo power ratings, pace, offensive and defensive rating, net rating and the four factors (eFG%, turnover rate, offensive rebound rate, free throw rate). Use when the user asks how a team is doing, who the best or fastest team is, why a team's record misleads, or wants two teams compared. Covers NBA, WNBA, men's and women's college. Do not use for a single game, see game-lookup or game-preview. Do not use for a player, see player-scouting. Do not use for where a team shoots from, see shot-zone-analysis."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Team Analysis

> **Default data tool:** DunkAPI (`dunkapi-tool`).
> `get_standings` (2 credits), `get_ratings` (2), `get_team_stats` (5). A full three-call team profile is 9 credits.

You read a team the way an analyst does: results first, then the efficiency that explains them, then whether the record is likely to hold.

## When to Use

- "How good are the Knicks?" / "Rank the East"
- "Who plays fastest?" / "Best defence in the league?"
- "Is Boston's record real or lucky?"
- Comparing two teams before a game or a series
- Producing team-level features for a model (see `feature-engineering`)

## When NOT to Use

- One game's box score or result, see `game-lookup`
- A full pre-game breakdown with injuries and odds, see `game-preview`
- Shot location and expected points by zone, see `shot-zone-analysis`
- Individual players, see `player-scouting`

## Commands Available

| Command | What it does | Credits |
|---------|-------------|---------|
| `get_standings` | Regular-season standings computed from every final game: W-L, home and away, points for and against, margin, last 10 | 2 |
| `get_ratings` | DunkAPI Elo ratings, ranked, as of the end of a season or today | 2 |
| `get_team_stats` | Pace, offensive, defensive and net rating per 100 possessions, four factors, three-point rate | 5 |
| `list_teams` | Team ids and abbreviations | 1 |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_advanced_team_stats` | `get_team_stats` |
| `get_power_rankings` | `get_ratings` (our Elo) or rank `get_team_stats` by `net_rating` |
| `get_lineup_stats`, `get_on_off` | None; lineup data is not served |
| `get_strength_of_schedule` | Derive from `list_games` plus `get_ratings` (see below) |

## Season Resolution

`season` is the year the season ends (2025-26 is `2026`). The 2026-27 NBA season opens Oct 20, 2026. Until a few weeks of games exist, `season: 2027` ratings and efficiency rest on almost nothing; use `season: 2026` and say it is last season. `get_team_stats` accepts `season_type`, so you can separate playoff efficiency from the regular season.

## How It Works

**Step 1: Results.** `get_standings` returns per team `wins losses home_wins home_losses away_wins away_losses points_for points_against avg_margin last10_wins win_pct`. The `conf_wins` and `conf_losses` fields read 0 in the responses seen for NBA, so do not rank on conference record from this tool.

**Step 2: Efficiency.** `get_team_stats` returns, per team:

| Field | Meaning |
|-------|---------|
| `pace` | Possessions per game |
| `off_rating`, `def_rating`, `net_rating` | Points scored, allowed and the difference, per 100 possessions |
| `efg_pct` | Effective FG%: `(fgm + 0.5 * tpm) / fga` |
| `tov_pct` | Turnover rate (fraction of possessions ending in a turnover) |
| `oreb_pct` | Offensive rebound rate |
| `ft_rate` | Free throw attempts per field goal attempt |
| `three_rate` | Share of shots that are threes |
| `opp_efg_pct` | Opponent effective FG% (the defensive half of factor one) |

Possessions are estimated as `FGA - OREB + TOV + 0.44 * FTA`, averaged over both teams (the API states this in `method`). Ratings are points per 100 possessions.

**Step 3: Strength.** `get_ratings` gives the Elo rating. 1500 is average; a 100-point gap is about a 64% favourite on a neutral floor. In g

Preview of the first 4,000 characters. Read full instructions →

walk-forward-validation7.39 KB

View saved version →

---
name: walk-forward-validation
description: "Validates basketball prediction models with chronological walk-forward splits instead of random k-fold: expanding or rolling windows, season-block folds, purge gaps, proper benchmarks (home-team baseline and the closing line), paired significance tests and the sample sizes needed to detect a small edge. Use when the user has a model and asks if it is any good, asks whether k-fold or a random split is okay (it is not), or wants to tune hyperparameters on time-ordered game data. Do not use for building the features, see feature-engineering. Do not use for probability reliability, see probability-calibration."
metadata:
  version: 1.0.0
  author: DunkAPI
---

# Walk-Forward Validation

> **Default data tool:** DunkAPI (`dunkapi-tool`) for game rows (`list_games`, 2 credits per page) and closing lines (`get_odds`). Validation itself needs no API calls.

Games are ordered in time and teams change slowly. A random split puts a team's April games in training and its March games in test; the model memorizes that team's season. That inflates every metric.

## When to Use

- "Is my NBA model any good?"
- "Can I use 5-fold cross-validation?" (no)
- "How many seasons should I train on?"
- Choosing between two models or two feature sets
- Deciding whether a result is signal or noise

## When NOT to Use

- Constructing features, see `feature-engineering`
- Judging whether 62% means 62%, see `probability-calibration`

## Commands Available

| Command | Role | Credits |
|---------|------|---------|
| `list_games` | The game table: dates, scores, season type | 2 per page |
| `get_odds` | Closing lines as the benchmark; `date` form is 10 credits for a day | 5 per game, 10 per date |

## Commands That Do NOT Exist

| Not available | Use instead |
|---------------|-------------|
| `get_train_test_split`, `get_cv_folds` | Split the table by date in code |
| `get_model_predictions` | Predictions come from your model |

## Why k-fold Fails Here

| Problem | Effect |
|---------|--------|
| Future games in training | The model sees a team's later form, injuries and trade effects |
| Neighbouring games are correlated | Test games look "easy" because adjacent games are in training |
| Season-level inputs (see `feature-engineering`) | Final-season summaries leak into every fold |
| Hyperparameters tuned on the test fold | Optimistic by construction |

## How It Works

**Step 1: Order by date, never shuffle.** Sort by `date`, then `game_id`. Games on the same night share a date; keep them together in a fold.

**Step 2: Choose a scheme.**

| Scheme | Use when | Layout |
|--------|----------|--------|
| Expanding window | Little data, stable relationships | Train seasons 1..k, test k+1 |
| Rolling window | Rules drift (pace, three-point rate) | Train the last W seasons, test the next |
| Within-season monthly | Need many test points, model refits cheaply | Train through month m, test month m+1 |

For NBA game models: train through season `s`, test season `s+1`, advance one season at a time. With 5 seasons that gives 4 tests of about 1,230 games each.

**Step 3: Gap.** If a feature uses a rolling window of W games, leave a gap of at least W games (or a few weeks) between train end and test start when features overlap the boundary. A feature built with `shift(1)` rolling windows needs no gap for the target, but any model fitted on a window ending at date d should not have been selected using later data.

**Step 4: Nested tuning.** Tune hyperparameters inside the training window (an inner walk-forward), freeze them, then score the outer test block. Never report the best of 50 tries on the same test block.

```python
def walk_forward(df, first_test_season, fit, predict):
    out = []
    for s in sorted(df.season.unique()):
        if s < first_test_season: continue
        train, test = df[df.season < s], df[df.season == s]
        model = fit(train)                       # tuning inside train only
        out.ap

Preview of the first 4,000 characters. Read full instructions →

Release notes

Initial release. Read-only NBA basketball data tools with OAuth sign-in and 14 workflow skills.

Declared in the saved package. Remote tools may change independently.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
DunkAPI
Keywords
See keywords
Commerce declaration
Does not support commerceThis does not establish whether access is free or paid.
Review scenarios
5 positive · 3 negativeScenario counts, not test results.

Declared capabilities

  • Look up NBA, WNBA and college teams and players
  • Read standings, schedules and scores
  • Read box scores, leaders and team stats
  • Read play-by-play and shot charts
  • Read sportsbook odds and prop lines (information only)

Package observed Nov 6, 2026.

Technical details
First seen
Oct 30, 2026 · 22:33 UTC
Last seen
Nov 6, 2026 · 06:00 UTC
Collection status
Collected

plugin_asdk_app_6ad146326fa48191a98ccaee7059af55

Download plugin data (JSON)

Plugin details: served from cache. Prepared . Refreshed when plugin data changes or after 6 hours. Your account and Follow status are live.