{
  "openapi": "3.0.3",
  "info": {
    "title": "PlayCaller Data API",
    "version": "1.4.0",
    "description": "The PlayCaller Data API delivers real-time and historical sports intelligence for fantasy, DFS, and AI developers.\n\n30 REST endpoints across NFL, MLB, NBA, College Football, and Soccer — plus an MCP server for AI workflow integration.\n\n## Key capabilities\n- **625+ active signals** scraped every 2 hours from ESPN NFL, MLB, and NBA injury reports\n- **13,606 canonical player identities** normalized across ESPN, Sleeper, Yahoo, NFL.com, and BallDontLie\n- **Full 2024 NFL season** backfilled into historical_performance (4,624 records)\n- **AI-first**: MCP server at `/mcp` for Cursor, Claude Desktop, and enterprise AI workflows\n- **5 sports** with live data pipelines: NFL, MLB, NBA, CFB, Soccer (EPL + MLS)\n\n## Authentication\nAll data endpoints require an `X-PlayCaller-Key` header. Keys are issued at [playcallerapp.com/developer](https://playcallerapp.com/developer). Trial keys work immediately — no credit card required.\n\nKey format: `pc_hob_...` (Hobbyist) or `pc_pro_...` (Pro)\n\n## Base URLs\n- Data endpoints (v1 prefix): `https://playcallerapp.com/v1`\n- Intelligence endpoints (no prefix): `https://playcallerapp.com/intelligence`\n- Analytics endpoint (no prefix): `https://playcallerapp.com/analytics`\n- MCP server: `https://playcallerapp.com/mcp`\n- Account endpoints: `https://playcallerapp.com/daas`\n\n## Tiers\n\n| Plan | Price | Monthly calls | Req/min | Notes |\n|------|-------|--------------|---------|-------|\n| Free Trial | 14 days | 100 req/day | 30 | Full Pro access, no card |\n| Hobbyist | $49/mo | 1,000 | 30 | All sports excl. CFB rankings, analytics, scoring leaders |\n| Pro | $149/mo | 10,000 | 60 | All endpoints including analytics and CFB rankings |\n| Enterprise | $1K–$5K/mo | Custom | 120+ | Dedicated SLA + custom builds |\n\n## Rate Limiting\n- `X-RateLimit-Limit`: Requests allowed per minute\n- `X-RateLimit-Remaining`: Remaining this window\n- `X-RateLimit-Reset`: Unix timestamp when window resets\n- `429` responses include a `Retry-After` header in seconds",
    "contact": {
      "name": "PlayCaller Support",
      "url": "https://playcallerapp.com/developer/docs"
    },
    "termsOfService": "https://playcallerapp.com/developer/terms"
  },
  "servers": [
    {
      "url": "https://playcallerapp.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Intelligence",
      "description": "Beat reporter signals, injury feeds, and historical analytics. These routes have no /v1 prefix."
    },
    {
      "name": "MLB",
      "description": "MLB player data, game states, standings, and fantasy scoring"
    },
    {
      "name": "NBA",
      "description": "NBA game scores, standings, teams, and player roster"
    },
    {
      "name": "CFB",
      "description": "College football scoreboard, standings, and rankings (Pro only)"
    },
    {
      "name": "Soccer",
      "description": "Soccer match scores and league tables (EPL + MLS)"
    },
    {
      "name": "Multi",
      "description": "Multi-sport discovery and public stats endpoints"
    },
    {
      "name": "Account",
      "description": "API key management, quota monitoring, and trial activation"
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol server — AI workflow integration for Cursor, Claude Desktop, and enterprise AI agents"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PlayCaller-Key",
        "description": "Your PlayCaller API key. Obtain one free at playcallerapp.com/developer."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error_code",
          "message",
          "documentation_url"
        ],
        "properties": {
          "error_code": {
            "type": "string",
            "example": "RATE_LIMIT_EXCEEDED"
          },
          "message": {
            "type": "string",
            "example": "Rate limit exceeded. Try again in 42 seconds."
          },
          "documentation_url": {
            "type": "string",
            "format": "uri",
            "example": "https://playcallerapp.com/developer/docs"
          },
          "upgrade_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "example": "https://playcallerapp.com/developer/checkout?tier=pro"
          }
        }
      },
      "ResponseMeta": {
        "type": "object",
        "properties": {
          "sport": {
            "type": "string",
            "example": "nfl"
          },
          "tier": {
            "type": "string",
            "example": "pro"
          },
          "calls_remaining_this_month": {
            "type": "integer",
            "example": 9843
          },
          "documentation_url": {
            "type": "string",
            "format": "uri",
            "example": "https://playcallerapp.com/developer/docs"
          }
        }
      },
      "BeatReporterSignal": {
        "type": "object",
        "required": [
          "id",
          "player_name",
          "team",
          "sport",
          "signal_type",
          "severity",
          "title",
          "summary",
          "source_name",
          "scraped_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "example": 48291
          },
          "player_name": {
            "type": "string",
            "example": "Christian McCaffrey"
          },
          "team": {
            "type": "string",
            "example": "SF"
          },
          "sport": {
            "type": "string",
            "description": "Sport this signal belongs to",
            "example": "nfl"
          },
          "signal_type": {
            "type": "string",
            "enum": [
              "injury",
              "depth_chart",
              "role_shift",
              "practice_report",
              "return_to_practice",
              "reddit_pain_signal"
            ],
            "example": "injury"
          },
          "severity": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "example": "high"
          },
          "title": {
            "type": "string",
            "example": "McCaffrey questionable with hamstring — listed DNP"
          },
          "summary": {
            "type": "string",
            "example": "Christian McCaffrey did not practice Wednesday with a hamstring injury. He is listed DNP and is considered questionable for Sunday."
          },
          "source_name": {
            "type": "string",
            "example": "ESPN NFL Injury Report"
          },
          "source_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "example": null
          },
          "scraped_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-05-13T08:14:00Z"
          },
          "is_active": {
            "type": "boolean",
            "example": true
          }
        }
      },
      "PlayerIdentity": {
        "type": "object",
        "required": [
          "playcaller_id",
          "full_name",
          "position",
          "team",
          "sport_key"
        ],
        "properties": {
          "playcaller_id": {
            "type": "string",
            "description": "Canonical PlayCaller player ID — stable across all platforms",
            "example": "pc_nfl_001234"
          },
          "full_name": {
            "type": "string",
            "example": "Christian McCaffrey"
          },
          "position": {
            "type": "string",
            "example": "RB"
          },
          "team": {
            "type": "string",
            "example": "SF"
          },
          "sport_key": {
            "type": "string",
            "enum": [
              "nfl",
              "mlb",
              "nba"
            ],
            "example": "nfl"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "injured",
              "inactive"
            ],
            "example": "active"
          },
          "platform_ids": {
            "type": "object",
            "description": "Platform-specific IDs for this player. Keys are platform names; values are IDs used by that platform.",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "espn": "3054211",
              "sleeper": "4034",
              "yahoo": "28849",
              "nfl.com": "mccaffrey-christian"
            }
          }
        }
      },
      "HistoricalTrend": {
        "type": "object",
        "properties": {
          "player_name": {
            "type": "string",
            "example": "Tyreek Hill"
          },
          "team": {
            "type": "string",
            "example": "MIA"
          },
          "position": {
            "type": "string",
            "example": "WR"
          },
          "sport": {
            "type": "string",
            "example": "nfl"
          },
          "season": {
            "type": "integer",
            "example": 2025
          },
          "week": {
            "type": "integer",
            "example": 8
          },
          "opponent": {
            "type": "string",
            "example": "BUF"
          },
          "fantasy_points": {
            "type": "number",
            "format": "float",
            "example": 28.4
          },
          "snap_pct": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 98.2
          },
          "target_share": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 34.1
          },
          "air_yards": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 142
          },
          "rushing_yards": {
            "type": "integer",
            "nullable": true,
            "example": 0
          },
          "rushing_tds": {
            "type": "integer",
            "nullable": true,
            "example": 0
          },
          "receiving_yards": {
            "type": "integer",
            "nullable": true,
            "example": 134
          },
          "receiving_tds": {
            "type": "integer",
            "nullable": true,
            "example": 2
          },
          "receptions": {
            "type": "integer",
            "nullable": true,
            "example": 8
          }
        }
      },
      "MLBPlayer": {
        "type": "object",
        "required": [
          "id",
          "full_name",
          "position",
          "team",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "PlayCaller MLB player ID",
            "example": "pc_mlb_001234"
          },
          "full_name": {
            "type": "string",
            "example": "Shohei Ohtani"
          },
          "position": {
            "type": "string",
            "enum": [
              "SP",
              "RP",
              "C",
              "1B",
              "2B",
              "3B",
              "SS",
              "OF",
              "DH"
            ],
            "example": "DH"
          },
          "team": {
            "type": "string",
            "example": "LAD"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "injured",
              "inactive"
            ],
            "example": "active"
          }
        }
      },
      "MLBPlayerStats": {
        "type": "object",
        "properties": {
          "player_id": {
            "type": "string",
            "example": "pc_mlb_001234"
          },
          "player_name": {
            "type": "string",
            "example": "Shohei Ohtani"
          },
          "game_date": {
            "type": "string",
            "format": "date",
            "example": "2026-05-01"
          },
          "fantasy_points": {
            "type": "number",
            "format": "float",
            "example": 18.5
          },
          "is_final": {
            "type": "boolean",
            "example": true
          },
          "batting": {
            "type": "object",
            "properties": {
              "h": {
                "type": "integer",
                "description": "Hits",
                "example": 2
              },
              "hr": {
                "type": "integer",
                "description": "Home Runs",
                "example": 1
              },
              "rbi": {
                "type": "integer",
                "description": "RBI",
                "example": 3
              },
              "sb": {
                "type": "integer",
                "description": "Stolen Bases",
                "example": 1
              },
              "r": {
                "type": "integer",
                "description": "Runs Scored",
                "example": 2
              },
              "bb": {
                "type": "integer",
                "description": "Walks",
                "example": 1
              },
              "ab": {
                "type": "integer",
                "description": "At Bats",
                "example": 4
              }
            }
          },
          "pitching": {
            "type": "object",
            "nullable": true,
            "properties": {
              "ip": {
                "type": "number",
                "format": "float",
                "description": "Innings Pitched",
                "example": 6.2
              },
              "k": {
                "type": "integer",
                "description": "Strikeouts",
                "example": 9
              },
              "sv": {
                "type": "integer",
                "description": "Saves",
                "example": 0
              }
            }
          }
        }
      },
      "MLBGame": {
        "type": "object",
        "properties": {
          "game_pk": {
            "type": "integer",
            "example": 745302
          },
          "game_date": {
            "type": "string",
            "format": "date",
            "example": "2026-05-01"
          },
          "state": {
            "type": "string",
            "enum": [
              "live",
              "final",
              "preview"
            ],
            "example": "live"
          },
          "home_team": {
            "type": "string",
            "example": "LAD"
          },
          "away_team": {
            "type": "string",
            "example": "SF"
          },
          "home_score": {
            "type": "integer",
            "nullable": true,
            "example": 4
          },
          "away_score": {
            "type": "integer",
            "nullable": true,
            "example": 2
          },
          "inning": {
            "type": "integer",
            "nullable": true,
            "example": 7
          },
          "is_final": {
            "type": "boolean",
            "example": false
          },
          "last_polled": {
            "type": "string",
            "format": "date-time",
            "example": "2026-05-01T22:14:05Z"
          }
        }
      },
      "ESPNGame": {
        "type": "object",
        "description": "Game state from ESPN feed (NBA, CFB, Soccer)",
        "properties": {
          "event_id": {
            "type": "string",
            "example": "espn_401584"
          },
          "game_date": {
            "type": "string",
            "format": "date",
            "example": "2026-05-01"
          },
          "game_time": {
            "type": "string",
            "example": "19:30"
          },
          "state": {
            "type": "string",
            "enum": [
              "pre",
              "in",
              "post"
            ],
            "example": "post"
          },
          "home_team": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "18"
              },
              "name": {
                "type": "string",
                "example": "Los Angeles Lakers"
              },
              "abbr": {
                "type": "string",
                "example": "LAL"
              },
              "logo": {
                "type": "string",
                "format": "uri",
                "example": "https://a.espncdn.com/i/teamlogos/nba/500/lal.png"
              },
              "score": {
                "type": "integer",
                "nullable": true,
                "example": 112
              }
            }
          },
          "away_team": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "2"
              },
              "name": {
                "type": "string",
                "example": "Boston Celtics"
              },
              "abbr": {
                "type": "string",
                "example": "BOS"
              },
              "logo": {
                "type": "string",
                "format": "uri",
                "example": "https://a.espncdn.com/i/teamlogos/nba/500/bos.png"
              },
              "score": {
                "type": "integer",
                "nullable": true,
                "example": 108
              }
            }
          },
          "period": {
            "type": "integer",
            "nullable": true,
            "example": 4
          },
          "period_label": {
            "type": "string",
            "nullable": true,
            "example": "Q4"
          },
          "clock": {
            "type": "string",
            "nullable": true,
            "example": "2:14"
          },
          "venue": {
            "type": "string",
            "nullable": true,
            "example": "Crypto.com Arena"
          },
          "broadcast": {
            "type": "string",
            "nullable": true,
            "example": "TNT"
          },
          "is_final": {
            "type": "boolean",
            "example": true
          },
          "last_polled": {
            "type": "string",
            "format": "date-time",
            "example": "2026-05-01T02:14:05Z"
          }
        }
      },
      "ESPNStanding": {
        "type": "object",
        "properties": {
          "rank": {
            "type": "integer",
            "example": 1
          },
          "team_id": {
            "type": "string",
            "example": "2"
          },
          "team_name": {
            "type": "string",
            "example": "Boston Celtics"
          },
          "team_abbr": {
            "type": "string",
            "example": "BOS"
          },
          "team_logo": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "conference": {
            "type": "string",
            "nullable": true,
            "example": "East"
          },
          "division": {
            "type": "string",
            "nullable": true,
            "example": "Atlantic"
          },
          "wins": {
            "type": "integer",
            "example": 64
          },
          "losses": {
            "type": "integer",
            "example": 18
          },
          "win_pct": {
            "type": "number",
            "format": "float",
            "example": 0.78
          },
          "games_back": {
            "type": "string",
            "nullable": true,
            "example": "-"
          },
          "streak": {
            "type": "string",
            "nullable": true,
            "example": "W3"
          },
          "home_record": {
            "type": "string",
            "nullable": true,
            "example": "36-5"
          },
          "away_record": {
            "type": "string",
            "nullable": true,
            "example": "28-13"
          },
          "conf_record": {
            "type": "string",
            "nullable": true,
            "example": "42-14"
          },
          "points_for": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 120.4
          },
          "points_against": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 109.8
          },
          "last_updated": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CFBRanking": {
        "type": "object",
        "properties": {
          "rank": {
            "type": "integer",
            "example": 1
          },
          "team_id": {
            "type": "string",
            "example": "cfb_alabama"
          },
          "team_name": {
            "type": "string",
            "example": "Alabama"
          },
          "team_abbr": {
            "type": "string",
            "example": "ALA"
          },
          "record": {
            "type": "string",
            "example": "12-0"
          },
          "points": {
            "type": "integer",
            "nullable": true,
            "example": 1550
          },
          "first_place_votes": {
            "type": "integer",
            "nullable": true,
            "example": 42
          },
          "prev_rank": {
            "type": "integer",
            "nullable": true,
            "example": 1
          },
          "week": {
            "type": "integer",
            "example": 15
          }
        }
      },
      "UsageStats": {
        "type": "object",
        "required": [
          "key_prefix",
          "tier",
          "is_trial",
          "calls_this_month",
          "calls_limit_month",
          "calls_remaining",
          "rate_limit_per_min",
          "reset_at"
        ],
        "properties": {
          "key_prefix": {
            "type": "string",
            "example": "pc_pro_"
          },
          "tier": {
            "type": "string",
            "enum": [
              "hobbyist",
              "pro",
              "enterprise"
            ],
            "example": "pro"
          },
          "is_trial": {
            "type": "boolean",
            "example": false
          },
          "trial_days_remaining": {
            "type": "integer",
            "nullable": true,
            "description": "Days left in trial (null if not in trial)",
            "example": null
          },
          "calls_this_month": {
            "type": "integer",
            "example": 157
          },
          "calls_limit_month": {
            "type": "integer",
            "example": 10000
          },
          "calls_remaining": {
            "type": "integer",
            "example": 9843
          },
          "rate_limit_per_min": {
            "type": "integer",
            "example": 60
          },
          "reset_at": {
            "type": "string",
            "format": "date-time",
            "description": "When monthly quota resets",
            "example": "2026-06-01T00:00:00Z"
          },
          "endpoint_breakdown": {
            "type": "object",
            "description": "Call counts per endpoint for the current billing period",
            "additionalProperties": {
              "type": "integer"
            },
            "example": {
              "/intelligence/news": 112,
              "/analytics/trends": 31,
              "/v1/mlb/players": 14
            }
          }
        }
      },
      "MCPTool": {
        "type": "object",
        "required": [
          "name",
          "description",
          "inputSchema"
        ],
        "properties": {
          "name": {
            "type": "string",
            "example": "get_injury_signals"
          },
          "description": {
            "type": "string",
            "example": "Returns active beat reporter injury signals filtered by sport and severity."
          },
          "inputSchema": {
            "type": "object",
            "description": "JSON Schema for tool arguments",
            "properties": {
              "type": {
                "type": "string",
                "example": "object"
              },
              "properties": {
                "type": "object",
                "additionalProperties": true
              },
              "required": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PublicStats": {
        "type": "object",
        "properties": {
          "active_users": {
            "type": "integer",
            "description": "Registered users with at least one login this month",
            "example": 4182
          },
          "active_signals": {
            "type": "integer",
            "description": "Beat reporter signals currently active across all sports",
            "example": 625
          },
          "players_tracked": {
            "type": "integer",
            "description": "Total canonical player identities in the database",
            "example": 13606
          },
          "sports_covered": {
            "type": "integer",
            "description": "Number of sports with live data pipelines",
            "example": 5
          },
          "platforms": {
            "type": "integer",
            "description": "External platforms with cross-platform player ID mappings",
            "example": 6
          }
        }
      }
    }
  },
  "paths": {
    "/intelligence/news": {
      "get": {
        "tags": [
          "Intelligence"
        ],
        "summary": "Live multi-sport player signals",
        "description": "Returns real-time player signals scraped every 2 hours from ESPN NFL, MLB, and NBA injury reports and beat reporter feeds. Signals surface before they appear on mainstream aggregators.\n\nIncludes injuries, depth chart changes, role shifts, practice participation, and return-to-practice designations across all three sports. Signal severity is calculated based on fantasy impact: a DNP for a workhorse RB is `high`; a minor hamstring note for a backup is `low`.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getIntelligenceNews",
        "parameters": [
          {
            "name": "severity",
            "in": "query",
            "description": "Filter by fantasy impact severity",
            "schema": {
              "type": "string",
              "enum": [
                "high",
                "medium",
                "low"
              ]
            },
            "example": "high"
          },
          {
            "name": "sport",
            "in": "query",
            "description": "Filter by sport (defaults to all)",
            "schema": {
              "type": "string",
              "enum": [
                "nfl",
                "mlb",
                "nba",
                "all"
              ]
            },
            "example": "nfl"
          },
          {
            "name": "team",
            "in": "query",
            "description": "Filter by 2-3 letter team abbreviation",
            "schema": {
              "type": "string",
              "maxLength": 3
            },
            "example": "SF"
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter by position (NFL: QB/RB/WR/TE/K; MLB: SP/OF/etc; NBA: PG/SG/etc)",
            "schema": {
              "type": "string"
            },
            "example": "WR"
          },
          {
            "name": "signal_type",
            "in": "query",
            "description": "Filter by signal category",
            "schema": {
              "type": "string",
              "enum": [
                "injury",
                "depth_chart",
                "role_shift",
                "practice_report",
                "return_to_practice"
              ]
            },
            "example": "injury"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results (default 25, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "Active player signals ordered by severity then recency",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BeatReporterSignal"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/intelligence/injuries": {
      "get": {
        "tags": [
          "Intelligence"
        ],
        "summary": "Active injury feed (multi-sport)",
        "description": "Filtered view of the signal feed returning only active injury designations across NFL, MLB, and NBA. Equivalent to `GET /intelligence/news?signal_type=injury` with convenience defaults tuned for DFS stack-building and lineup decisions.\n\n625+ active signals are re-scraped every 2 hours. High-severity signals are available before mainstream platforms aggregate them.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getIntelligenceInjuries",
        "parameters": [
          {
            "name": "severity",
            "in": "query",
            "description": "Minimum severity level",
            "schema": {
              "type": "string",
              "enum": [
                "high",
                "medium",
                "low"
              ]
            },
            "example": "high"
          },
          {
            "name": "sport",
            "in": "query",
            "description": "Sport filter (defaults to nfl)",
            "schema": {
              "type": "string",
              "enum": [
                "nfl",
                "mlb",
                "nba",
                "all"
              ]
            },
            "example": "nfl"
          },
          {
            "name": "team",
            "in": "query",
            "description": "2-3 letter team abbreviation",
            "schema": {
              "type": "string",
              "maxLength": 3
            },
            "example": "KC"
          },
          {
            "name": "player",
            "in": "query",
            "description": "Partial player name search (case-insensitive)",
            "schema": {
              "type": "string"
            },
            "example": "Mahomes"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results (default 50, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "Active injury signals ordered by severity then recency",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BeatReporterSignal"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/analytics/trends": {
      "get": {
        "tags": [
          "Intelligence"
        ],
        "summary": "Historical performance trends (Pro)",
        "description": "Game-by-game performance logs for NFL (2024 full season, 4,624 records) and MLB players. Each row represents one game: full stat line plus calculated fantasy points under PPR, half-PPR, or standard scoring.\n\nUse this endpoint to calculate targets-per-route, air yards share, snap consistency, and multi-week usage trends — the signals that separate week-winning waiver adds from noise.\n\n**Tier access:** Pro only",
        "operationId": "getAnalyticsTrends",
        "parameters": [
          {
            "name": "sport",
            "in": "query",
            "description": "Sport to query (default: nfl)",
            "schema": {
              "type": "string",
              "enum": [
                "nfl",
                "mlb",
                "all"
              ]
            },
            "example": "nfl"
          },
          {
            "name": "player_name",
            "in": "query",
            "description": "Partial player name (case-insensitive)",
            "schema": {
              "type": "string"
            },
            "example": "McCaffrey"
          },
          {
            "name": "team",
            "in": "query",
            "description": "2-3 letter team abbreviation",
            "schema": {
              "type": "string",
              "maxLength": 3
            },
            "example": "SF"
          },
          {
            "name": "position",
            "in": "query",
            "description": "Position (QB/RB/WR/TE for NFL; SP/OF/etc for MLB)",
            "schema": {
              "type": "string"
            },
            "example": "WR"
          },
          {
            "name": "season",
            "in": "query",
            "description": "Season year (NFL: 2024; MLB: 2024)",
            "schema": {
              "type": "integer"
            },
            "example": 2024
          },
          {
            "name": "week",
            "in": "query",
            "description": "NFL week number (1–18)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 18
            },
            "example": 8
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max records (default 50, max 500)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "Game-by-game historical performance records",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HistoricalTrend"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/players": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "List active MLB players",
        "description": "Returns all active MLB players (966 total). Positions, teams, and statuses are normalized from MLB Stats API and reconciled against ESPN for accuracy.\n\nFilter by position and team to build DFS pools or lineup constraints without doing the normalization yourself.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listMLBPlayers",
        "parameters": [
          {
            "name": "position",
            "in": "query",
            "description": "Filter by position",
            "schema": {
              "type": "string",
              "enum": [
                "SP",
                "RP",
                "C",
                "1B",
                "2B",
                "3B",
                "SS",
                "OF",
                "DH"
              ]
            },
            "example": "SP"
          },
          {
            "name": "team",
            "in": "query",
            "description": "3-letter MLB team abbreviation",
            "schema": {
              "type": "string"
            },
            "example": "NYY"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by player status",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "injured",
                "inactive"
              ]
            },
            "example": "active"
          },
          {
            "name": "search",
            "in": "query",
            "description": "Partial name search (case-insensitive)",
            "schema": {
              "type": "string"
            },
            "example": "Ohtani"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results (default 50, max 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 50
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Pagination offset",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "example": 0
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of MLB players",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MLBPlayer"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/players/{id}": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "Get MLB player by ID",
        "description": "Returns the full profile for a single MLB player by PlayCaller ID. Use `/v1/mlb/players?search=` to find IDs by name.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getMLBPlayer",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "PlayCaller MLB player ID (format: pc_mlb_XXXXXX)",
            "schema": {
              "type": "string"
            },
            "example": "pc_mlb_001234"
          }
        ],
        "responses": {
          "200": {
            "description": "MLB player profile",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/MLBPlayer"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "404": {
            "description": "Player not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "PLAYER_NOT_FOUND",
                  "message": "No player found with ID pc_mlb_999999.",
                  "documentation_url": "https://playcallerapp.com/developer/docs#mlb"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/players/{id}/stats": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "Game-by-game stats for an MLB player",
        "description": "Returns daily batting and pitching stat lines with pre-calculated fantasy points. Useful for tracking recent form, streaks, and park-factor-adjusted production.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getMLBPlayerStats",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "PlayCaller MLB player ID",
            "schema": {
              "type": "string"
            },
            "example": "pc_mlb_001234"
          },
          {
            "name": "date",
            "in": "query",
            "description": "Filter to a specific game date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max game logs (default 30, max 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 30
            },
            "example": 30
          }
        ],
        "responses": {
          "200": {
            "description": "Player game-by-game stat log",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "player_id": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MLBPlayerStats"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "404": {
            "description": "Player not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/teams": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "All 30 MLB teams",
        "description": "Returns metadata for all 30 MLB teams including roster depth. Abbreviations are normalized (e.g. NYY, BOS, LAD).\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listMLBTeams",
        "responses": {
          "200": {
            "description": "30 MLB teams with roster counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "abbreviation": {
                            "type": "string",
                            "example": "NYY"
                          },
                          "full_name": {
                            "type": "string",
                            "example": "New York Yankees"
                          },
                          "roster_size": {
                            "type": "integer",
                            "example": 26
                          },
                          "active_players": {
                            "type": "integer",
                            "example": 24
                          }
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/teams/{team}/roster": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "MLB team roster",
        "description": "Returns the active roster for a specific team. Filter by position to pull only starting pitchers or corner infielders for lineup construction.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getMLBTeamRoster",
        "parameters": [
          {
            "name": "team",
            "in": "path",
            "required": true,
            "description": "3-letter MLB team abbreviation (e.g. NYY, LAD)",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 3
            },
            "example": "NYY"
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter by position",
            "schema": {
              "type": "string",
              "enum": [
                "SP",
                "RP",
                "C",
                "1B",
                "2B",
                "3B",
                "SS",
                "OF",
                "DH"
              ]
            },
            "example": "SP"
          }
        ],
        "responses": {
          "200": {
            "description": "Team roster",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "team": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MLBPlayer"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "404": {
            "description": "Team abbreviation not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/games": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "Live and scheduled MLB games",
        "description": "Live inning-by-inning game state from the MLB Stats API pipeline. Defaults to today's games. Scores update on a polling cycle throughout the game day.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listMLBGames",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Game date (YYYY-MM-DD, defaults to today)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "state",
            "in": "query",
            "description": "Filter by game state",
            "schema": {
              "type": "string",
              "enum": [
                "live",
                "final",
                "preview"
              ]
            },
            "example": "live"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max games (default 30, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "example": 30
          }
        ],
        "responses": {
          "200": {
            "description": "MLB game states",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MLBGame"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/standings": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "MLB division standings",
        "description": "Current MLB standings by division sourced from ESPN. Includes win %, streak, home/away splits, and runs differential.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getMLBStandings",
        "parameters": [
          {
            "name": "season",
            "in": "query",
            "description": "Season year (defaults to current)",
            "schema": {
              "type": "integer"
            },
            "example": 2026
          },
          {
            "name": "division",
            "in": "query",
            "description": "Filter by division name (partial match: \"AL East\", \"NL West\")",
            "schema": {
              "type": "string"
            },
            "example": "AL East"
          }
        ],
        "responses": {
          "200": {
            "description": "MLB standings by division",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "season": {
                      "type": "integer"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ESPNStanding"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/scoring/leaders": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "MLB fantasy scoring leaders (Pro)",
        "description": "Top fantasy scorers for any game day, ranked by total points. Uses the PlayCaller scoring engine with standard roto weights (H, HR, RBI, SB, R, BB for batters; IP, K, SV for pitchers).\n\nUseful for identifying daily stack targets and late-swap pivots before lock.\n\n**Tier access:** Pro only",
        "operationId": "getMLBScoringLeaders",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Game date (YYYY-MM-DD, defaults to most recent game day)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter by position",
            "schema": {
              "type": "string",
              "enum": [
                "SP",
                "RP",
                "C",
                "1B",
                "2B",
                "3B",
                "SS",
                "OF",
                "DH"
              ]
            },
            "example": "OF"
          },
          {
            "name": "team",
            "in": "query",
            "description": "3-letter team abbreviation",
            "schema": {
              "type": "string"
            },
            "example": "NYY"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max leaders (default 25, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "Fantasy scoring leaderboard for date",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MLBPlayerStats"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mlb/scoring/categories": {
      "get": {
        "tags": [
          "MLB"
        ],
        "summary": "MLB rotisserie category leaders (Pro)",
        "description": "Top 10 players per rotisserie scoring category (HR, RBI, SB, R, BB, IP, K, SV) for a given date. Ideal for roto league managers tracking category races and daily contributions.\n\n**Tier access:** Pro only",
        "operationId": "getMLBScoringCategories",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Game date (YYYY-MM-DD, defaults to most recent game day)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          }
        ],
        "responses": {
          "200": {
            "description": "Top 10 per rotisserie category",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "description": "Keys: home_runs, rbi, stolen_bases, runs, walks, innings_pitched, strikeouts, saves",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/MLBPlayerStats"
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nba/games": {
      "get": {
        "tags": [
          "NBA"
        ],
        "summary": "NBA game scores and schedule",
        "description": "Live scores and scheduled NBA games from the ESPN feed. Includes venue, broadcast network, period clock, and team logos for display-ready integrations.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listNBAGames",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Game date (YYYY-MM-DD, defaults to today)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "state",
            "in": "query",
            "description": "Game state filter",
            "schema": {
              "type": "string",
              "enum": [
                "pre",
                "in",
                "post"
              ]
            },
            "example": "in"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max games (default 30, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "example": 30
          }
        ],
        "responses": {
          "200": {
            "description": "NBA game states",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ESPNGame"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nba/standings": {
      "get": {
        "tags": [
          "NBA"
        ],
        "summary": "NBA conference standings",
        "description": "Current NBA standings including conference, division, win %, streak, and home/away split records. Filterable by conference.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getNBAStandings",
        "parameters": [
          {
            "name": "season",
            "in": "query",
            "description": "Season year (defaults to current)",
            "schema": {
              "type": "integer"
            },
            "example": 2026
          },
          {
            "name": "conference",
            "in": "query",
            "description": "Filter by conference",
            "schema": {
              "type": "string",
              "enum": [
                "East",
                "West"
              ]
            },
            "example": "East"
          }
        ],
        "responses": {
          "200": {
            "description": "NBA standings by conference",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "season": {
                      "type": "integer"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ESPNStanding"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nba/teams": {
      "get": {
        "tags": [
          "NBA"
        ],
        "summary": "All 30 NBA teams",
        "description": "All 30 NBA teams with conference, division, and ESPN team logo URL. Filterable by conference.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listNBATeams",
        "parameters": [
          {
            "name": "conference",
            "in": "query",
            "description": "Filter by conference",
            "schema": {
              "type": "string",
              "enum": [
                "East",
                "West"
              ]
            },
            "example": "West"
          }
        ],
        "responses": {
          "200": {
            "description": "NBA teams",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "team_id": {
                            "type": "string"
                          },
                          "team_name": {
                            "type": "string"
                          },
                          "team_abbr": {
                            "type": "string"
                          },
                          "conference": {
                            "type": "string"
                          },
                          "division": {
                            "type": "string"
                          },
                          "team_logo": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true
                          }
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nba/players": {
      "get": {
        "tags": [
          "NBA"
        ],
        "summary": "NBA players (2,000 seeded)",
        "description": "2,000 NBA players seeded from BallDontLie for the 2025 season. Includes ESPN headshot URLs, jersey numbers, and position. Searchable by name, position, or team.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listNBAPlayers",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Partial player name (case-insensitive)",
            "schema": {
              "type": "string"
            },
            "example": "LeBron"
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter by position",
            "schema": {
              "type": "string",
              "enum": [
                "PG",
                "SG",
                "SF",
                "PF",
                "C"
              ]
            },
            "example": "PG"
          },
          {
            "name": "team",
            "in": "query",
            "description": "3-letter team abbreviation",
            "schema": {
              "type": "string"
            },
            "example": "LAL"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results (default 50, max 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "NBA players",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "athlete_id": {
                            "type": "string"
                          },
                          "full_name": {
                            "type": "string"
                          },
                          "position": {
                            "type": "string"
                          },
                          "team_abbr": {
                            "type": "string"
                          },
                          "team_name": {
                            "type": "string"
                          },
                          "jersey": {
                            "type": "string",
                            "nullable": true
                          },
                          "headshot": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true
                          },
                          "status": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cfb/games": {
      "get": {
        "tags": [
          "CFB"
        ],
        "summary": "College football scoreboard (Pro)",
        "description": "CFB game scores and schedule from ESPN. Covers FBS games including conference championships and bowl games.\n\n**Tier access:** Pro only",
        "operationId": "listCFBGames",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Game date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-09-05"
          },
          {
            "name": "state",
            "in": "query",
            "description": "Game state filter",
            "schema": {
              "type": "string",
              "enum": [
                "pre",
                "in",
                "post"
              ]
            },
            "example": "post"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max games (default 50, max 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "CFB games",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ESPNGame"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cfb/standings": {
      "get": {
        "tags": [
          "CFB"
        ],
        "summary": "College football conference standings (Pro)",
        "description": "CFB standings by conference. Includes win %, conference record, and streak. Useful for playoff scenario modeling.\n\n**Tier access:** Pro only",
        "operationId": "getCFBStandings",
        "parameters": [
          {
            "name": "season",
            "in": "query",
            "description": "Season year (defaults to current)",
            "schema": {
              "type": "integer"
            },
            "example": 2026
          },
          {
            "name": "conference",
            "in": "query",
            "description": "Filter by conference (partial match: \"SEC\", \"Big Ten\")",
            "schema": {
              "type": "string"
            },
            "example": "SEC"
          }
        ],
        "responses": {
          "200": {
            "description": "CFB standings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "season": {
                      "type": "integer"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ESPNStanding"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cfb/rankings": {
      "get": {
        "tags": [
          "CFB"
        ],
        "summary": "AP / Coaches Poll / CFP rankings (Pro)",
        "description": "AP Top 25, Coaches Poll, and CFP rankings by week. Each poll returns ranked teams with first-place votes, total points, and previous rank movement.\n\n**Tier access:** Pro only",
        "operationId": "getCFBRankings",
        "parameters": [
          {
            "name": "season",
            "in": "query",
            "description": "Season year (defaults to current)",
            "schema": {
              "type": "integer"
            },
            "example": 2026
          },
          {
            "name": "poll",
            "in": "query",
            "description": "Poll filter (partial match: \"AP\", \"Coaches\", \"CFP\")",
            "schema": {
              "type": "string"
            },
            "example": "AP"
          },
          {
            "name": "week",
            "in": "query",
            "description": "Week number (1–16)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 16
            },
            "example": 14
          }
        ],
        "responses": {
          "200": {
            "description": "CFB rankings grouped by poll",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "season": {
                      "type": "integer"
                    },
                    "polls": {
                      "type": "object",
                      "description": "Keys are poll names; values are ranked team arrays",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/CFBRanking"
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required for this endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "TIER_INSUFFICIENT",
                  "message": "This endpoint requires a Pro subscription.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/tiers",
                  "upgrade_url": "https://playcallerapp.com/developer/checkout?tier=pro"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/soccer/games": {
      "get": {
        "tags": [
          "Soccer"
        ],
        "summary": "Soccer match scores (EPL + MLS)",
        "description": "Live and historical match scores for EPL and MLS. Includes team logos, venue, broadcast, and score state for display-ready applications.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "listSoccerGames",
        "parameters": [
          {
            "name": "league",
            "in": "query",
            "description": "League filter (omit for both leagues)",
            "schema": {
              "type": "string",
              "enum": [
                "epl",
                "mls"
              ]
            },
            "example": "epl"
          },
          {
            "name": "date",
            "in": "query",
            "description": "Match date (YYYY-MM-DD, defaults to today)",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "state",
            "in": "query",
            "description": "Game state filter",
            "schema": {
              "type": "string",
              "enum": [
                "pre",
                "in",
                "post"
              ]
            },
            "example": "post"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max matches (default 30, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "example": 30
          }
        ],
        "responses": {
          "200": {
            "description": "Soccer matches",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/ESPNGame"
                          },
                          {
                            "properties": {
                              "league": {
                                "type": "string",
                                "example": "epl"
                              }
                            }
                          }
                        ]
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/soccer/standings": {
      "get": {
        "tags": [
          "Soccer"
        ],
        "summary": "Soccer league table (EPL + MLS)",
        "description": "Current league tables for EPL and/or MLS. Includes points, goal difference, wins, draws, losses, and home/away splits.\n\n**Tier access:** Hobbyist, Pro",
        "operationId": "getSoccerStandings",
        "parameters": [
          {
            "name": "league",
            "in": "query",
            "description": "League (epl or mls; omit for both)",
            "schema": {
              "type": "string",
              "enum": [
                "epl",
                "mls"
              ]
            },
            "example": "epl"
          },
          {
            "name": "season",
            "in": "query",
            "description": "Season year (defaults to current)",
            "schema": {
              "type": "integer"
            },
            "example": 2026
          }
        ],
        "responses": {
          "200": {
            "description": "Soccer standings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "league": {
                      "type": "string",
                      "example": "all"
                    },
                    "season": {
                      "type": "integer"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/ESPNStanding"
                          },
                          {
                            "properties": {
                              "league": {
                                "type": "string"
                              },
                              "ties": {
                                "type": "integer",
                                "nullable": true
                              }
                            }
                          }
                        ]
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ResponseMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports": {
      "get": {
        "tags": [
          "Multi"
        ],
        "summary": "Supported sports and endpoint discovery",
        "description": "Returns all supported sports with their available endpoints and status. Use this to programmatically discover which data is live vs. coming soon for your tier.\n\n**Tier access:** All tiers",
        "operationId": "listSports",
        "responses": {
          "200": {
            "description": "Sports and available endpoints by tier",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "endpoint": {
                      "type": "string"
                    },
                    "sports": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sport": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "endpoints": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/daas/usage": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "API key quota and usage breakdown",
        "description": "Returns current quota consumption, rate limits, tier details, and per-endpoint call breakdown for the authenticated key. Use this to build usage dashboards or trigger pre-quota alerts in your application.\n\n**Tier access:** All tiers",
        "operationId": "getDaaSUsage",
        "responses": {
          "200": {
            "description": "API key usage statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/UsageStats"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "key_prefix": "pc_pro_",
                    "tier": "pro",
                    "is_trial": false,
                    "trial_days_remaining": null,
                    "calls_this_month": 157,
                    "calls_limit_month": 10000,
                    "calls_remaining": 9843,
                    "rate_limit_per_min": 60,
                    "reset_at": "2026-06-01T00:00:00Z",
                    "endpoint_breakdown": {
                      "/intelligence/news": 112,
                      "/analytics/trends": 31,
                      "/v1/mlb/players": 14
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/daas/key-info": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "API key metadata",
        "description": "Returns tier, trial status, and creation date for the API key passed as `?key=` query parameter. Useful for building key verification flows in your own applications without exposing the full usage payload.\n\n**Tier access:** All tiers (no header auth required — pass key as query param)",
        "operationId": "getDaaSKeyInfo",
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "description": "The PlayCaller API key to look up",
            "schema": {
              "type": "string"
            },
            "example": "pc_pro_abc123"
          }
        ],
        "responses": {
          "200": {
            "description": "API key metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "hobbyist",
                        "pro",
                        "enterprise"
                      ]
                    },
                    "is_trial": {
                      "type": "boolean"
                    },
                    "trial_days_remaining": {
                      "type": "integer",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "404": {
            "description": "Key not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/daas/trial/start": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Start a 14-day free trial",
        "description": "Creates a Hobbyist-tier API key for a 14-day free trial. No credit card required. Key is returned in the response and emailed to the provided address. Limit: one trial per email.\n\n**Auth:** No API key required",
        "operationId": "startDaaSTrial",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "example": "dev@example.com"
                  },
                  "use_case": {
                    "type": "string",
                    "description": "What you are building (optional, helps us improve)",
                    "example": "DFS lineup optimizer for NFL season"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Trial key created — full response contains API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "api_key": {
                      "type": "string",
                      "description": "Your new PlayCaller API key. Store it securely.",
                      "example": "pc_hob_xxxxxxxx"
                    },
                    "tier": {
                      "type": "string",
                      "example": "hobbyist"
                    },
                    "trial_ends_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "message": {
                      "type": "string",
                      "example": "Your 14-day trial is active. Key emailed to dev@example.com."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Email already has an active trial or subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/daas/register-key": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Register an existing API key",
        "description": "Associates an existing DaaS API key with a user account for dashboard access. Used internally by the developer dashboard onboarding flow.\n\n**Auth:** No API key required",
        "operationId": "registerDaaSKey",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "api_key"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "example": "dev@example.com"
                  },
                  "api_key": {
                    "type": "string",
                    "example": "pc_pro_abc123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key registered to account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "INVALID_API_KEY",
                  "message": "The provided API key is invalid or has been revoked.",
                  "documentation_url": "https://playcallerapp.com/developer/docs"
                }
              }
            }
          },
          "404": {
            "description": "API key not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "Retry-After": {
                "description": "Seconds until rate limit resets",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error_code": "RATE_LIMIT_EXCEEDED",
                  "message": "Rate limit exceeded. Try again in 42 seconds.",
                  "documentation_url": "https://playcallerapp.com/developer/docs/rate-limits"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "get": {
        "tags": [
          "MCP"
        ],
        "summary": "MCP server info and tool discovery",
        "description": "Returns human-readable JSON describing the PlayCaller MCP server: endpoint URL, auth method, all available tools with descriptions, and links to documentation.\n\nPoint Cursor, Claude Desktop, or any MCP-compatible client at this URL to discover available tools automatically.\n\n**Auth:** No authentication required for GET (tool invocation requires X-PlayCaller-Key)",
        "operationId": "getMCPInfo",
        "security": [],
        "responses": {
          "200": {
            "description": "MCP server info with tool list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "example": "PlayCaller MCP Server"
                    },
                    "version": {
                      "type": "string",
                      "example": "1.0.0"
                    },
                    "protocol": {
                      "type": "string",
                      "example": "MCP over HTTP (JSON-RPC 2.0)"
                    },
                    "endpoint": {
                      "type": "string",
                      "format": "uri",
                      "example": "https://playcallerapp.com/mcp"
                    },
                    "auth": {
                      "type": "string",
                      "example": "X-PlayCaller-Key: <your_daas_key>"
                    },
                    "tools": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MCPTool"
                      }
                    },
                    "docs": {
                      "type": "string",
                      "format": "uri",
                      "example": "https://playcallerapp.com/developer#mcp"
                    },
                    "get_key": {
                      "type": "string",
                      "format": "uri",
                      "example": "https://playcallerapp.com/developer#pricing"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "MCP"
        ],
        "summary": "MCP JSON-RPC 2.0 endpoint",
        "description": "The PlayCaller MCP server implements Anthropic's Model Context Protocol over HTTP transport. Send JSON-RPC 2.0 messages to invoke sports intelligence tools from any AI application.\n\n**Available tools:**\n- `get_injury_signals` — Active beat reporter signals filtered by sport/severity\n- `get_player_identity` — Resolve a player name or platform ID across ESPN, Sleeper, Yahoo, NFL.com\n- `get_anomaly_scores` — Players with usage patterns deviating from 3-season baseline (score 0–100)\n- `get_prediction_markets` — Active Kalshi prop markets with AI confidence scores\n- `get_player_projections` — AI fantasy point projections using recent game logs and injury signals\n\n**Config for Cursor (.cursor/mcp.json):**\n```json\n{\n  \"mcpServers\": {\n    \"playcaller\": {\n      \"url\": \"https://playcallerapp.com/mcp\",\n      \"headers\": { \"X-PlayCaller-Key\": \"YOUR_API_KEY\" }\n    }\n  }\n}\n```\n\n**Tier access:** Any active DaaS key (Hobbyist, Pro, Enterprise)",
        "operationId": "invokeMCPTool",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "enum": [
                      "2.0"
                    ],
                    "example": "2.0"
                  },
                  "id": {
                    "type": "integer",
                    "example": 1
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "tools/list",
                      "tools/call",
                      "ping"
                    ],
                    "example": "tools/call"
                  },
                  "params": {
                    "type": "object",
                    "description": "Required for tools/call: `name` (tool name) and `arguments` (tool-specific args)",
                    "properties": {
                      "name": {
                        "type": "string",
                        "example": "get_injury_signals"
                      },
                      "arguments": {
                        "type": "object",
                        "example": {
                          "sport": "nfl",
                          "severity": "high",
                          "limit": 5
                        }
                      }
                    }
                  }
                }
              },
              "examples": {
                "listTools": {
                  "summary": "List available tools",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "tools/list"
                  }
                },
                "callInjurySignals": {
                  "summary": "Get high-severity NFL injuries",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 2,
                    "method": "tools/call",
                    "params": {
                      "name": "get_injury_signals",
                      "arguments": {
                        "sport": "nfl",
                        "severity": "high",
                        "limit": 5
                      }
                    }
                  }
                },
                "resolvePlayer": {
                  "summary": "Resolve player identity",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 3,
                    "method": "tools/call",
                    "params": {
                      "name": "get_player_identity",
                      "arguments": {
                        "name": "Christian McCaffrey",
                        "sport": "nfl"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response (always 200 — errors returned in body per JSON-RPC spec)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "example": "2.0"
                    },
                    "id": {
                      "type": "integer",
                      "example": 1
                    },
                    "result": {
                      "type": "object",
                      "description": "Present on success",
                      "properties": {
                        "content": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "example": "text"
                              },
                              "text": {
                                "type": "string",
                                "description": "JSON-encoded tool result"
                              }
                            }
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "object",
                      "description": "Present on error",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "example": -32601
                        },
                        "message": {
                          "type": "string",
                          "example": "Method not found: tools/unknown"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/public/stats": {
      "get": {
        "tags": [
          "Multi"
        ],
        "summary": "Platform stats (unauthenticated)",
        "description": "Public endpoint returning live platform statistics: registered users, active signals, total players tracked, sports covered, and platforms integrated. No API key required.\n\n**Tier access:** Public — no auth required",
        "operationId": "getPublicStats",
        "security": [],
        "responses": {
          "200": {
            "description": "Current platform statistics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicStats"
                }
              }
            }
          }
        }
      }
    }
  }
}