← FastballAPICONTENT HISTORY

Update to FastballAPI

Snapshot Oct 30, 2026 · 00:06 UTC · version 1.0.0

Collection source: downloaded plugin package.

WHAT CHANGED

First saved snapshot

No earlier snapshot is available to establish a change.

Save FastballAPI and check future changes in Following.

Up to 10 plugins free · no card required.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Analyzes an MLB pitcher's arsenal: pitch types, usage, average and top velocity, whiff rate per swing, ball rate, usage by count, velocity by inning and platoon splits, from FastballAPI pitch-by-pitch data. Use when the user asks what a pitcher throws, which pitch gets whiffs, how his velocity changes through a game or season, or what his pitch mix means for strikeouts. Do not use for season ERA or WHIP lines: see player-scouting. Do not use for pricing a strikeout prop: see prop-modeling. Do not use for college baseball: no pitch data exists there.",
  "included_files": [],
  "name": "pitch-mix-analysis",
  "skill_md_contents": "---\nname: pitch-mix-analysis\ndescription: \"Analyzes an MLB pitcher's arsenal: pitch types, usage, average and top velocity, whiff rate per swing, ball rate, usage by count, velocity by inning and platoon splits, from FastballAPI pitch-by-pitch data. Use when the user asks what a pitcher throws, which pitch gets whiffs, how his velocity changes through a game or season, or what his pitch mix means for strikeouts. Do not use for season ERA or WHIP lines: see player-scouting. Do not use for pricing a strikeout prop: see prop-modeling. Do not use for college baseball: no pitch data exists there.\"\nmetadata:\n  version: 1.0.0\n  author: FastballAPI\n---\n\n# Pitch Mix Analysis\n\n> **Default data tool:** FastballAPI (`fastballapi-tool`).\n> `get_pitch_mix` (5 credits) gives the arsenal summary. `get_pitches` (10 credits, up to 2,000 rows a call) gives every pitch for custom cuts. `search_players` (1) first.\n\nYou read a pitcher's arsenal the way a scout reads a scouting report: what he throws, how hard, how often, and what batters do against it. MLB only. College baseball has no pitch rows.\n\n## When to Use\n\n- \"What does Tarik Skubal throw?\"\n- \"Which of his pitches gets the most whiffs?\"\n- Usage vs whiff: does he throw his best pitch enough?\n- Velocity trend within a start or across a season\n- Changes in pitch mix between seasons\n- Inputs for a strikeout model (see `prop-modeling`)\n\n## When NOT to Use\n\n- Season ERA, WHIP, K/9: `player-scouting`\n- Hitter-side batted-ball profile: `spray-chart-analysis`\n- Run value of outcomes: `run-value-analysis`\n- College pitchers: not available\n\n## Commands Available\n\n| Command | What it does | Credits |\n|---------|--------------|---------|\n| `get_pitch_mix` | Per pitch type: `pitches`, `usage`, `avg_velocity`, `max_velocity`, `whiff_rate`, `ball_rate`, `in_play`; takes `pitcher_id`, `season` | 5 |\n| `get_pitches` | Every pitch: `at_bat_id`, `pitch_number`, `inning`, `half`, `balls`, `strikes`, `pitch_type`, `pitch_type_name`, `velocity`, `px`, `py`, `result`, `in_play`; filters `game_id`, `pitcher_id`, `batter_id`, `season`, `pitch_type`, `limit` up to 2,000, `offset` | 10 |\n| `search_players` | Find `pitcher_id` | 1 |\n| `get_player` | Season line to set the context | 5 |\n\n## Commands That Do NOT Exist\n\n| Not available | Use instead |\n|---------------|-------------|\n| `get_spin_rate`, `get_movement`, `get_extension` | Not available. No spin, break or release data |\n| `get_stuff_plus`, `get_pitch_value` | Not available. Build run value from `get_plate_appearances` outcomes |\n| `get_pitch_mix` for a game | Not available. Use `get_pitches` with `game_id` and aggregate |\n| `get_pitch_arsenal_by_batter_hand` | Use `get_pitches` with `batter_id` filters or batch by handedness in code |\n| `get_bullpen_mix` | Same tools, run per reliever |\n\n## Coverage\n\n- Every pitch since 2018. For 2015 to 2017, about 98 to 99% of each season's pitches.\n- Pitch type and velocity are on 96% or more of each season's pitches, and 99.8% or more from 2020.\n- Automatic balls and strikes (intentional walks, pitch-timer violations) are not pitches.\n- `px` and `py` are ESPN's pitch-location frame in pixels, as sent. They are not feet and the strike zone boundaries are not given. Use them for relative location (up/down, in/out) within one pitcher, not for zone-rate claims against an official zone.\n- Pitch type labels are ESPN's feed classifications (FF, SI, FC, SL, CH, CU, KC). Some pitchers' four-seam and sinker labels blur.\n\n## How It Works\n\n**Step 1: Resolve the pitcher.** `search_players` with `name`. Check `position` is SP or RP. Real: Tarik Skubal, `player_id` 42409.\n\n**Step 2: Arsenal summary.**\n\n```json\nPOST /v1/get_pitch_mix\n{\"pitcher_id\": \"42409\", \"season\": 2025}\n```\n\nReal response (2025, trimmed to the four main pitches):\n\n```json\n{\"data\": {\"pitcher\": {\"id\": \"42409\", \"name\": \"Tarik Skubal\"}, \"season\": 2025, \"pitches\": 3152,\n \"mix\": [\n  {\"pitch_type\": \"CH\", \"name\": \"Changeup\",     \"pitches\": 974, \"usage\": 0.309, \"avg_velocity\": 87.6, \"max_velocity\": 92,  \"whiff_rate\": 0.488, \"ball_rate\": 0.30,  \"in_play\": 161},\n  {\"pitch_type\": \"FF\", \"name\": \"Four-seam FB\", \"pitches\": 953, \"usage\": 0.302, \"avg_velocity\": 97.2, \"max_velocity\": 102, \"whiff_rate\": 0.291, \"ball_rate\": 0.293, \"in_play\": 141},\n  {\"pitch_type\": \"SI\", \"name\": \"Sinker\",       \"pitches\": 734, \"usage\": 0.233, \"avg_velocity\": 96.9, \"max_velocity\": 101, \"whiff_rate\": 0.189, \"ball_rate\": 0.272, \"in_play\": 131},\n  {\"pitch_type\": \"SL\", \"name\": \"Slider\",       \"pitches\": 407, \"usage\": 0.129, \"avg_velocity\": 89.8, \"max_velocity\": 94,  \"whiff_rate\": 0.262, \"ball_rate\": 0.324, \"in_play\": 65}]}}\n```\n\n**Step 3: Read it correctly.**\n\n- `whiff_rate` is per swing (swinging strikes divided by swings), not per pitch. A 48.8% whiff rate on the changeup means about half the swings against it missed.\n- `usage` is share of all pitches in the season, not by count or batter hand.\n- `in_play` is balls in play on that pitch, a sample-size check: 161 changeups in play against 65 sliders.\n- `ball_rate` is balls per pitch. High whiff with high ball rate is chase-driven, not zone-driven.\n\nObservations from the real numbers: the changeup is his most-used and highest-whiff pitch (31% usage, .488); the two fastballs together are 53% of his pitches but whiff much less (.291 four-seam, .189 sinker); the sinker, at the same velocity as the four-seam, gets far fewer whiffs, so it is not where his strikeouts come from (what it does to contact needs the plate-appearance data).\n\n**Step 4: Strikeout shape.** A pitcher's strikeout rate is roughly the sum over pitches of usage times swing rate times whiff rate (plus called strikes). `get_pitch_mix` does not give swing rate. If you need the full decomposition, count swings in `get_pitches` using the `result` field. List the distinct `result` values from the first page before filtering; a sample row shows `strike-looking` and `ball`, and swinging strikes appear under their own value. Never guess the label.\n\n**Step 5: Custom cuts with `get_pitches`.** 10 credits per call, so plan:\n\n```json\nPOST /v1/get_pitches\n{\"pitcher_id\": \"42409\", \"season\": 2025, \"limit\": 2000, \"offset\": 0}\n```\n\nA season of about 3,150 pitches needs two pages (offset 0 and 2000). Real row shape:\n\n```json\n{\"game_id\": \"401809272\", \"at_bat_id\": \"4018092720101\", \"pitch_number\": 1, \"inning\": 1, \"half\": \"bottom\",\n \"pitcher_id\": \"42409\", \"batter_id\": \"36488\", \"balls\": 0, \"strikes\": 0,\n \"pitch_type\": \"FF\", \"pitch_type_name\": \"Four-seam FB\", \"velocity\": 97, \"px\": 108, \"py\": 178,\n \"result\": \"strike-looking\", \"in_play\": false}\n```\n\nCuts worth making:\n\n| Cut | How | What it tells you |\n|-----|-----|-------------------|\n| Usage by count | group by `balls`, `strikes`, `pitch_type` | Does he go to the changeup when ahead? |\n| First-pitch mix | `balls == 0 and strikes == 0` | Predictability |\n| Velocity by inning | mean `velocity` by `inning`, one game or many | Fatigue; early-inning vs late |\n| Velocity by season month | group pitches by game date from `game_id` joins | Season-long drop or injury sign |\n| vs batter hand | join `batter_id` to `bats` from `search_players` | Platoon usage |\n| Pitch to pitch | order by `at_bat_id`, `pitch_number` | Sequencing |\n\n**Step 6: Velocity trend rules.**\n\n1. Compare the same pitch type only; a mix change moves the pitcher-level average.\n2. Use at least 30 pitches of a type per cell.\n3. A 1 mph drop in a four-seam over 3 consecutive starts is worth flagging; a single start is not. Weather, mound and radar calibration vary by ballpark; say that and do not diagnose injuries.\n\n## Sample Size\n\n| Metric | Rule of thumb before trusting |\n|--------|-------------------------------|\n| Usage by pitch | 200+ pitches of the pitcher |\n| Whiff rate per pitch type | 100+ swings (about 300 pitches for a changeup) |\n| Platoon split usage | 500+ pitches per side |\n| Velocity change | 3 starts, 30+ pitches per type per start |\n\nThese are practical floors, not API outputs.\n\n## Credit Usage\n\n| Operation | Credits |\n|-----------|---------|\n| Find pitcher + arsenal | 6 |\n| One game of pitches | 10 |\n| One season of pitches (two pages) | 20 |\n| Pitcher comparison (two arsenals) | 12 |\n\n## Anti-patterns\n\n| Mistake | Why it is wrong | Do This |\n|---------|-----------------|---------|\n| Calling whiff rate \"per pitch\" | It is per swing | Say per swing |\n| Averaging whiff rates weighted by pitch count | Needs swing counts | Recompute from `get_pitches` or avoid |\n| Using `px`/`py` as feet | Pixel frame as sent | Relative location only |\n| Comparing 2017 velocity to 2020 without caution | Coverage is fuller from 2018, near-complete from 2020 | State coverage |\n| Reading a sinker's low whiff as poor stuff | It targets ground balls | Judge by contact outcome |\n| Naming spin or movement | Not in the data | Say it is not available |\n| Doing this for a college pitcher | No pitch rows | Say so |\n\n## Output Format\n\n```\nTarik Skubal, 2025: 3,152 pitches\nChangeup 30.9% | 87.6 avg (92 max) | whiff 48.8% per swing | ball 30.0%\nFour-seam 30.2% | 97.2 avg (102 max) | whiff 29.1% | ball 29.3%\nSinker 23.3% | 96.9 avg | whiff 18.9% | ball 27.2%\nSlider 12.9% | 89.8 avg | whiff 26.2% | ball 32.4%\nRead: changeup carries the strikeouts; fastballs set it up. Sample is a full season.\n```\n\n## What to Do Next\n\n| You found | Next | Skill |\n|-----------|------|-------|\n| High-whiff pitch | Build a strikeout projection | `prop-modeling` |\n| Pitcher context needed | Season line and workload | `player-scouting` |\n| Which pitches get hit hard | Batted-ball profile of opponents | `spray-chart-analysis` |\n| Outcome value by pitch | Run value | `run-value-analysis` |\n"
}

SHA-256 of public snapshot: 13195e7a1816222a3068d007ac6936289d4ba5b8ed53808dd422098a62de4563