{
  "openapi": "3.0.1",
  "info": {
    "title": "MLB Stats Scraper 💰$2/1K — Scores, Standings & Stats",
    "description": "Scrape statsapi.mlb.com for teams, rosters, schedules, live scores, standings, season batting, pitching and fielding stats, box scores and league leaders — at $2 per 1,000 rows, half what comparable MLB scrapers charge. Structured JSON, CSV or Excel.",
    "version": "0.1",
    "x-build-id": "yTLWNrocuPjEyd3JT"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/blackfalcondata~mlb-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-blackfalcondata-mlb-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/blackfalcondata~mlb-scraper/runs": {
      "post": {
        "operationId": "runs-sync-blackfalcondata-mlb-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/blackfalcondata~mlb-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-blackfalcondata-mlb-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "title": "⚾ Data Type",
            "enum": [
              "players",
              "teams",
              "schedule",
              "standings",
              "playerStats",
              "gameDetails",
              "leaders"
            ],
            "type": "string",
            "description": "What to scrape. Players = the season roster with full batting, pitching and fielding lines (the default). Teams = every club with league, division and venue. Schedule = games with scores and status. Standings = live division and wild-card tables. Player Stats = season stat lines for the players or clubs you name. Box Scores = one row per player per game. Leaders = the league leaderboards.",
            "default": "players"
          },
          "query": {
            "title": "🔍 Search Term(s)",
            "type": "string",
            "description": "Name to match, full or partial (e.g. \"Ohtani\", \"Aaron Judge\", \"Rodriguez\"). On Players it matches the player name; on the other data types it matches the names the record carries, so \"Yankees\" finds their games, their standing and their players' box-score lines. Case-insensitive and substring-based. LEAVE EMPTY for the complete set."
          },
          "season": {
            "title": "📅 Season",
            "minimum": 1876,
            "maximum": 2100,
            "type": "integer",
            "description": "Season year to pull, e.g. 2026. Defaults to the current year. Historical seasons are served the same way."
          },
          "sportId": {
            "title": "⚾ League Level",
            "minimum": 1,
            "maximum": 600,
            "type": "integer",
            "description": "1 = Major League Baseball (default). 11 = Triple-A, 12 = Double-A, 13 = High-A, 14 = Single-A."
          },
          "seasons": {
            "title": "📅 Seasons (multiple)",
            "type": "array",
            "description": "Several season years in one run, e.g. 2024, 2025, 2026. Overrides 📅 Season when set. Each season is fetched separately, so ten seasons cost ten times one season.",
            "items": {
              "type": "string"
            }
          },
          "teamIds": {
            "title": "🏟️ Team IDs",
            "type": "array",
            "description": "Limit to these clubs, by statsapi team id (e.g. 147 = New York Yankees, 119 = Los Angeles Dodgers). Leave empty for every club. Run the Teams data type once to get the full id list.",
            "items": {
              "type": "string"
            }
          },
          "playerIds": {
            "title": "🧢 Player IDs",
            "type": "array",
            "description": "Player Stats only. Limit to these players, by statsapi person id (e.g. 660271 = Shohei Ohtani). Empty falls back to the clubs in 🏟️ Team IDs, and empty again to the whole season roster.",
            "items": {
              "type": "string"
            }
          },
          "gamePks": {
            "title": "📋 Game IDs",
            "type": "array",
            "description": "Box Scores only. The games to pull, by statsapi gamePk. Empty means every game the Schedule filters below select — so a date plus a club is enough, no ids needed.",
            "items": {
              "type": "string"
            }
          },
          "date": {
            "title": "📆 Date",
            "type": "string",
            "description": "Schedule and Box Scores. A single day, YYYY-MM-DD (e.g. 2025-07-04). Shorthand for setting From and To to the same day. A value that is not a date stops the run rather than being ignored."
          },
          "fromDate": {
            "title": "📆 From Date",
            "type": "string",
            "description": "Schedule and Box Scores. Start of the date range, YYYY-MM-DD. Leave both dates empty for the whole season."
          },
          "toDate": {
            "title": "📆 To Date",
            "type": "string",
            "description": "Schedule and Box Scores. End of the date range, YYYY-MM-DD."
          },
          "leagueId": {
            "title": "🏅 League",
            "enum": [
              "both",
              "AL",
              "NL"
            ],
            "type": "string",
            "description": "Standings and Leaders. Both leagues, or just the American or National League.",
            "default": "both"
          },
          "statGroup": {
            "title": "📈 Stat Group",
            "enum": [
              "all",
              "hitting",
              "pitching",
              "fielding"
            ],
            "type": "string",
            "description": "Player Stats and Leaders. Keep every player, or narrow to those with a season line in one group — choosing Pitching returns pitchers, not position players with an empty pitching line. All three lines are still delivered on every row that survives the filter.",
            "default": "all"
          },
          "gameType": {
            "title": "🎬 Game Type",
            "enum": [
              "R",
              "S",
              "P",
              "F",
              "D",
              "L",
              "W",
              "A"
            ],
            "type": "string",
            "description": "Schedule, Box Scores and Leaders. Which part of the season counts. Postseason covers the Wild Card, Division Series, League Championship and World Series together; pick one of those to narrow it further.",
            "default": "R"
          },
          "leaderCategories": {
            "title": "🏆 Leaderboards",
            "type": "array",
            "description": "Leaders only. Which boards to pull, by statsapi category (homeRuns, battingAverage, runsBattedIn, stolenBases, earnedRunAverage, strikeouts, wins, saves, …). Empty returns those eight.",
            "items": {
              "type": "string"
            }
          },
          "includeOdds": {
            "title": "💰 Betting Odds & Win Probability",
            "type": "boolean",
            "description": "Schedule only. Add the sportsbook line for each game — money line with its open and close, run line, over/under total — plus the win probability with the bookmaker margin divided out, and an independent model projection. NOT CHARGED: unlike the enrichment options above, odds carry no fee of their own, only a little run time. One exception worth knowing: with Incremental Mode on, a moving line counts as a change, so games whose odds shifted come back as updated rows and are charged at the usual per-record rate. Leave odds off if you want incremental runs to react only to the schedule itself. The official MLB feed carries no odds at all, so this is read from a second source and matched to each game by club and final score; a game that cannot be matched safely is left without odds rather than handed another game line.",
            "default": false
          },
          "startUrls": {
            "title": "🔗 Start URLs",
            "type": "array",
            "description": "Optional. Point the run at a roster universe with a statsapi.mlb.com URL of the form https://statsapi.mlb.com/api/v1/sports/1/players?season=2025 — sportId 1 is MLB, 11 to 14 are the minor-league levels. This is how you reach a roster the season and sport inputs cannot name. Each URL becomes its own task and results are merged and deduped by record ID. A URL of any other shape is ignored and the run falls back to the other inputs — and if there are none, the run stops and says so rather than quietly browsing the whole roster you did not ask for.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "maxResults": {
            "title": "💯 Max Results",
            "minimum": 0,
            "maximum": 50000,
            "type": "integer",
            "description": "Maximum total records (0 = unlimited). Box Scores is the one exception: unlimited there is a whole season of play-by-play rows, far more than one run can hold, so it asks you to narrow by date, club or game first.",
            "default": 25
          },
          "includeDetails": {
            "title": "📋 Include Full Details",
            "type": "boolean",
            "description": "Fetch full records — season stats, biography, position, handedness and current club. Turn off for a faster, name-only run.",
            "default": true
          },
          "includeRosterStatus": {
            "title": "🏥 Include Roster & Injury Status",
            "type": "boolean",
            "description": "Players data type only — these fields ride on the player record, so a Player Stats, Box Score, Schedule, Standings or Leaders run is not enriched by this switch and is not charged for it. Add each player's current roster status — Active, Injured 10-Day, Injured 60-Day, Reassigned to Minors, Released — plus the date it took effect. Roughly doubles the amount of data fetched per player. Requires 📋 Include Full Details; without it this option is skipped and not charged.",
            "default": false
          },
          "includeAwards": {
            "title": "🏆 Include Awards",
            "type": "boolean",
            "description": "Players data type only — these fields ride on the player record, so a Player Stats, Box Score, Schedule, Standings or Leaders run is not enriched by this switch and is not charged for it. Add All-Star and Futures Game selections and similar honours, with the season each was won. Adds about 60% to the data fetched per player. Needs 📋 Include Full Details switched on — otherwise it is skipped, and not charged.",
            "default": false
          },
          "includeTransactions": {
            "title": "📋 Include Transaction History",
            "type": "boolean",
            "description": "Players data type only — these fields ride on the player record, so a Player Stats, Box Score, Schedule, Standings or Leaders run is not enriched by this switch and is not charged for it. Add signings, trades and injured-list placements with their dates and the league's own wording. This is where injury dates come from. Substantially increases the data fetched per player — leave off unless you need the history. Only runs when 📋 Include Full Details is on; skipped and not charged otherwise.",
            "default": false
          },
          "compact": {
            "title": "📦 Compact Output",
            "type": "boolean",
            "description": "Core fields only (for AI-agent/MCP workflows).",
            "default": false
          },
          "excludeEmptyFields": {
            "title": "Exclude empty fields from output",
            "type": "boolean",
            "description": "Drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards.",
            "default": false
          },
          "incrementalMode": {
            "title": "♻️ Incremental Mode",
            "type": "boolean",
            "description": "Compare against previous run state. stateKey is optional — defaults to a value derived from search inputs (queries, startUrls) so different filter sets never share state.",
            "default": false
          },
          "stateKey": {
            "title": "🔑 State Key",
            "type": "string",
            "description": "Optional. Stable identifier for the tracked search universe. Leave empty to auto-generate from the inputs that SELECT the universe — search terms, start URLs, data type, season, league level and the id filters. Date filters are deliberately NOT part of it, so two runs over different date windows share one history on purpose: a window is a slice of the same universe, not a different one. Set this yourself when you want two runs kept apart regardless."
          },
          "emitUnchanged": {
            "title": "🔄 Emit Unchanged Records",
            "type": "boolean",
            "description": "When incremental mode is on, also emit records whose content has not changed since the last run.",
            "default": false
          },
          "emitExpired": {
            "title": "⚰️ Emit Expired Records",
            "type": "boolean",
            "description": "When incremental mode is on, also emit records that were seen before but are no longer found. NOT available on a date-filtered run: a run narrowed by 📅 Date or the From/To range has only seen a slice of the season, so it cannot prove anything disappeared and will never emit a removal however long you leave it on. Use it on a run that covers the whole universe.",
            "default": false
          },
          "skipReposts": {
            "title": "🚫 Skip Duplicates",
            "type": "boolean",
            "description": "When incremental, skip records whose content matches an expired record from a prior run (cross-run duplicate detection).",
            "default": false
          },
          "telegramToken": {
            "title": "🔑 Telegram Bot Token",
            "type": "string",
            "description": "Telegram bot token (from @BotFather). Required for Telegram notifications."
          },
          "telegramChatId": {
            "title": "💬 Telegram Chat ID",
            "type": "string",
            "description": "Telegram chat or channel ID (e.g. \"-100123456789\"). Required when telegramToken is set."
          },
          "discordWebhookUrl": {
            "title": "🎮 Discord Webhook URL",
            "type": "string",
            "description": "Discord incoming webhook URL. Server Settings → Integrations → Webhooks → New Webhook."
          },
          "slackWebhookUrl": {
            "title": "💼 Slack Webhook URL",
            "type": "string",
            "description": "Slack incoming webhook URL. api.slack.com/messaging/webhooks."
          },
          "notificationLimit": {
            "title": "📊 Max Records Per Notification",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of records included in each notification message (1–20).",
            "default": 5
          },
          "notifyOnlyChanges": {
            "title": "🔄 Notify Only New/Updated",
            "type": "boolean",
            "description": "When Incremental Mode is on, only send notifications for NEW and UPDATED records. Has no effect outside incremental mode.",
            "default": false
          },
          "whatsappAccessToken": {
            "title": "📱 WhatsApp Access Token",
            "type": "string",
            "description": "WhatsApp Cloud API permanent access token (System User token from Meta Business). Recipient must have messaged the business number within the last 24h (service-conversation window — free since Nov 2024)."
          },
          "whatsappPhoneNumberId": {
            "title": "📞 WhatsApp Phone Number ID",
            "type": "string",
            "description": "Your WhatsApp Business phone-number ID (numeric, from Meta dashboard). Required when whatsappAccessToken is set."
          },
          "whatsappTo": {
            "title": "📲 WhatsApp Recipient",
            "type": "string",
            "description": "Recipient phone in E.164 format without + (e.g. \"436641234567\"). Recipient must have messaged your business number within last 24h."
          },
          "webhookUrl": {
            "title": "🪝 Generic Webhook URL",
            "type": "string",
            "description": "Receives a JSON POST with {metadata, items} after each run. Universal escape hatch for n8n / Make / Zapier / custom backends."
          },
          "webhookHeaders": {
            "title": "📋 Webhook Headers",
            "type": "object",
            "description": "Optional JSON object of custom headers (e.g. {\"Authorization\":\"Bearer ...\"})."
          },
          "appConnector": {
            "title": "Send results to a connected app",
            "type": "string",
            "description": "Optional. Pick a connected app under Settings → API & Integrations to receive your results. Best-effort across MCP connectors as Apify expands its catalog."
          },
          "mcpIssueTeam": {
            "title": "Issue tracker team",
            "type": "string",
            "description": "Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one."
          },
          "descriptionFormat": {
            "title": "📝 Description Format",
            "type": "string",
            "description": "Not used by this Actor. MLB records carry no free-text description field, so this setting has nothing to act on; it is accepted only so existing callers do not break.",
            "default": "all"
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}