# FPL Intelligence - Picks, Optimizer, Watchlist, History (`constructive_calm/fpl-intelligence`) Actor

Fantasy Premier League intelligence: weekly captain & transfer picks, wildcard optimizer, mini-league insights, price-change predictor, manager dashboard, live tracker, 10 seasons of history.

- **URL**: https://apify.com/constructive\_calm/fpl-intelligence.md
- **Developed by:** [Omar Eldeeb](https://apify.com/constructive_calm) (community)
- **Categories:** Developer tools, Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## FPL Intelligence — Picks, Optimizer, Watchlist, History

Fantasy Premier League intelligence as a one-call API. Replaces parts of Fantasy Football Hub (£19.99/yr), FPL Review ($5/mo), Fantasy Football Scout (£25/yr), and LiveFPL Premium with pay-per-event pricing — and uniquely gives you the full historical archive (2016-17 → 2025-26) for FPL model training.

### What does this Actor do?

Seven modes, each producing a distinct output shape:

- **`gameweek_picks`** — top 5 captain candidates / transfer-in targets / differentials / sell candidates for the upcoming gameweek, with composite scoring + reason tags. Optional Gemini AI verdict.
- **`wildcard_optimizer`** — optimal 15-man squad given a budget, position quotas (2/5/5/3), 3-per-club cap, lock/exclude lists. Auto-picks captain + vice + formation.
- **`mini_league_intel`** — given any league ID, surfaces captain spread + true differential picks (high in this league, low globally) + you-vs-the-field deltas.
- **`price_change_predictor`** — tonight's predicted risers and fallers from net-transfer-rate vs ownership (community-known FPL price algorithm).
- **`manager_dashboard`** — given a manager ID, full season trajectory + chip usage + best/worst captains (with real points from live data) + per-transfer P&L over a 5-GW window.
- **`live_tracker`** — single snapshot OR pollable refresh during a live gameweek. Per-manager live points + per-league live standings.
- **`historical_seasons`** — 10 years of FPL data via the [vaastav community archive](https://github.com/vaastav/Fantasy-Premier-League). Per-gameweek, season totals, fixtures, or players. `schemaTier` flag (`full` / `no_xg` / `basic`) documents per-season coverage honestly.

All data is pulled from the [public Fantasy Premier League API](https://fantasy.premierleague.com/api/) (no auth, no key, no proxy required) plus the vaastav GitHub archive. Stress-tested at 250 concurrent requests with zero rate-limiting (full report in `_research/fpl-stress/` if interested).

### Why use this Actor?

1. **FPL managers** scheduling weekly picks runs — pipe captain/transfer recommendations to Slack/Discord/Sheets without writing API code.
2. **Mini-league competitors** tracking the field — see who captained what, find the player who's 80% owned in your league but 5% globally, and get differentials before your rivals.
3. **Price-change watchers** running a nightly job — predict tonight's £0.1m moves before they hit, time your transfers around the threshold.
4. **Data scientists / model builders** — pull every per-gameweek snapshot from 2016-17 onwards with a single mode call. xG/xA/xGI fields available from 2021-22.
5. **FPL content creators** (podcasters, newsletter writers, Twitter analysts) — generate weekly captain briefings, Gemini-powered verdicts, mini-league scouting reports.

### How to use this Actor

1. Pick a `mode` (see modes list above).
2. Fill in the relevant section's fields (manager IDs, league IDs, gameweek, etc.).
3. Hit Run, or schedule it on Apify's scheduler.
4. Export the dataset as JSON / CSV / Excel, or pipe to a webhook.

Free trial: **first 10 chargeable events per run are free**. Charges apply only after that.

### Input examples

#### 1. Gameweek picks (default)

```json
{
  "mode": "gameweek_picks",
  "picksOptions": {
    "topN": 5,
    "differentialThresholdPct": 5.0,
    "fixtureLookahead": 3
  },
  "enableAiVerdict": false
}
````

Returns 4 categories × 5 rows each (captain / transfer-in / differential / sell). Set `enableAiVerdict: true` to add a 1-paragraph Gemini brief at +$0.05.

#### 2. Wildcard optimizer with budget cap

```json
{
  "mode": "wildcard_optimizer",
  "optimizerOptions": {
    "budget": 100.0,
    "lockedPlayers": ["430", "328"],
    "excludedTeams": ["1"]
  }
}
```

Locks Haaland (id 430) and Salah (id 328), excludes Arsenal players (team id 1). Returns one row with the optimal 15-man squad, formation, total cost.

#### 3. Mini-league intel for the global Overall league

```json
{
  "mode": "mini_league_intel",
  "leagueIds": ["314"],
  "leagueOptions": {
    "topManagersPerLeague": 50,
    "compareToManagerId": "1000000"
  }
}
```

Returns a league summary (captain spread + differentials + your-vs-field comparison) plus 50 league\_manager rows.

#### 4. Tonight's price changes

```json
{
  "mode": "price_change_predictor",
  "pricePredictorOptions": {
    "minConfidence": 0.5,
    "includeNeutral": false
  }
}
```

Returns predicted risers + fallers above 50% confidence, sorted by transfer activity.

#### 5. Your season dashboard

```json
{
  "mode": "manager_dashboard",
  "managerIds": ["1000000"]
}
```

Returns one dashboard row + one transfer\_roi row per transfer you've made (P\&L vs the player you sold).

#### 6. Live tracker — poll every 60s during the GW

```json
{
  "mode": "live_tracker",
  "managerIds": ["1000000"],
  "leagueIds": ["314"],
  "gameweek": 36,
  "liveOptions": { "refreshIntervalSec": 60, "maxSnapshots": 30 }
}
```

Snapshots every minute for up to 30 polls (~30 min of live coverage).

#### 7. Historical training data — 4 most recent seasons

```json
{
  "mode": "historical_seasons",
  "historicalOptions": {
    "seasons": ["2021-22", "2022-23", "2023-24", "2024-25"],
    "dataType": "per_gameweek"
  },
  "maxItems": 100000
}
```

Pulls ~22,800 rows × 4 = ~91,200 per-player-per-GW records with full xG/xA fields. About 6 seconds total runtime + ~22 MB of data.

### Output

Every row has a `type` field discriminating its shape. Sample `captain_pick`:

```json
{
  "type": "captain_pick",
  "scrapedAt": "2026-05-10T08:48:56.437Z",
  "source": "fpl-api",
  "player": {
    "id": 430, "code": 223094, "webName": "Haaland",
    "team": { "id": 13, "name": "Man City", "shortName": "MCI" },
    "position": "FWD", "cost": 14.7, "status": "a",
    "selectedByPercent": 64.3, "form": 5.5,
    "expectedGoalInvolvements": 27.42, "expectedGoalInvolvementsPer90": 0.86,
    "epNext": 6, "setPiece": { "penaltiesOrder": 1, "cornersOrder": null, "freekicksOrder": null }
  },
  "gameweek": 37,
  "upcomingFixture": { "id": 362, "home": {...}, "away": {...}, "...": "..." },
  "pickScore": 62.7,
  "fixtureLookaheadDifficulty": 2.7,
  "reasonTags": ["good_form", "set_piece_taker", "easy_fixture", "home_advantage", "xgi_leader", "high_ep_next", "current_dreamteam"],
  "rank": 1
}
```

#### Data fields per row type

| Type | Key fields |
|---|---|
| `captain_pick` / `transfer_in` / `differential` | player (full normalized object), pickScore, reasonTags, rank, upcomingFixture, fixtureLookaheadDifficulty |
| `sell_candidate` | player, reasonTags (e.g. "injured", "form\_drop"), rank |
| `optimizer_squad` | squad\[15] with isStarter/isCaptain/isViceCaptain flags, totalCost, formation, totalExpectedPoints |
| `league_summary` | league, gameweek, topCaptainCounts, topDifferentials, comparedManagerDelta |
| `league_manager` | league, manager, rank, lastRank, eventTotal, total, captainElementId |
| `price_change_prediction` | player, predictedDirection (rise/fall/neutral), netTransferRate, confidence, predictedNewCost |
| `manager_dashboard` | manager, perGameweek\[], chipUsage\[], captainHistory\[], bestCaptain, worstCaptain, pastSeasons\[] |
| `manager_transfer_roi` | manager, transfer (gw, in, out), pointsAfter5gw, verdict |
| `live_snapshot` | snapshotAt, gameweek, manager (live points + XI), league (top managers ranked by live points), bonusFinalized |
| `historical_player_gw` | season, schemaTier, name, team, position, round, total\_points, expected\_goals, value, ... (40+ raw fields) |
| `ai_verdict` | gameweek, brief, captainRecommendation, topTransferAdvice |

### Pricing

Pay only for what you use. **First 10 chargeable events per run are free** (trial cap).

| Event | Price |
|---|---|
| `apify-actor-start` | $0.01 (auto-fired by platform per GB memory) |
| `gameweek-picks-fetched` | **$0.05** (primary — bundles all 4 pick categories) |
| `optimizer-run` | $0.10 |
| `mini-league-analyzed` | $0.02 (per league) |
| `price-change-predicted` | $0.005 (per flagged player) |
| `manager-dashboard-fetched` | $0.01 (per manager) |
| `live-snapshot` | $0.005 (per snapshot) |
| `historical-snapshot-fetched` | $0.01 (per season-gameweek pair) |
| `ai-verdict` | $0.05 (opt-in only) |

#### Typical run costs

| Workflow | Events | Total cost |
|---|---|---|
| Weekly captain pick run | 1 picks + 1 actor-start | $0.06 |
| Picks + AI verdict | 1 picks + 1 ai + 1 start | $0.11 |
| Wildcard optimizer | 1 optimizer + 1 start | $0.11 |
| Daily 50-manager mini-league check | 1 league + 1 start | $0.03 |
| 100-player price-change scan | up to 100 × $0.005 + start | up to $0.51 |
| Manager dashboard | 1 manager + 1 start | $0.02 |
| Live tracker (30 snapshots) | 30 × $0.005 + start | $0.16 |
| Full 2024-25 season pull (38 GWs) | 38 × $0.01 + start | $0.39 |

Within trial (first 10 events free), most workflows are essentially free for casual use.

### Tips & advanced options

- **Schedule it.** Run `gameweek_picks` every Friday at 10am UTC, pipe to Slack via Apify's webhook integration. Run `price_change_predictor` daily at 11pm UTC (~3 hours before FPL's nightly price update).
- **Lock premiums in optimizer.** The optimizer maximizes sum of `ep_next` within constraints, which often surfaces value picks over premium attackers due to the 3-per-club cap. If you prefer star power, set `lockedPlayers: ["430"]` to force Haaland in.
- **Mini-league differentials.** A "differential" in this actor is a player highly owned in your league (>25%) but rare globally (<10%). Useful for finding what the elite are doing that the masses haven't caught onto.
- **Historical schema tiers.** Seasons 2022-23 onwards have full xG/xA/xGI/xGC fields. 2020-21 to 2021-22 have most fields but no Opta xG. Earlier seasons (2016-17 to 2019-20) have basic stats only — name/round/total\_points/value but no position/team/xP. The `schemaTier` field on each row tells you what to expect.
- **Live tracker memo.** When polling, the actor clears its in-run cache between snapshots so each one fetches fresh live data.

### Legal / data sources

- Fantasy Premier League data: pulled from `fantasy.premierleague.com/api/` — the same JSON endpoints powering the official FPL website. Public, unauthenticated, and used by every FPL tool that exists. Note: this is not an officially documented public API; the Premier League could change or restrict it at any time without notice. The endpoints have been stable since ~2017.
- Historical archive: pulled from [vaastav/Fantasy-Premier-League](https://github.com/vaastav/Fantasy-Premier-League) (MIT-licensed community archive maintained by Vaastav Anand and contributors).
- All FPL data and team names © Premier League. Use of this actor is for personal analytical use; no warranty of accuracy is implied.
- Price-change predictions are based on a community-known heuristic (net-transfer-rate-vs-ownership thresholds), not an official FPL formula. Confidence values are empirical, not contractual.

### FAQ

**Q: How do I find my manager ID?**
A: Log into the FPL website, navigate to "Points" or "Pick Team", and look at the URL. It will be `fantasy.premierleague.com/entry/<your-id>/event/N`.

**Q: How do I find a mini-league ID?**
A: From your league's standings page, the URL is `fantasy.premierleague.com/leagues/<league-id>/standings/c`.

**Q: Why is the optimizer leaving budget unspent?**
A: The optimizer uses a 1-for-1 swap heuristic which can get stuck on the 3-per-club cap (e.g. it can't add Haaland because there are already 3 Man City players in the squad). To work around: pre-lock your premium picks via `lockedPlayers`, then the optimizer fills the rest around them.

**Q: How accurate are the price-change predictions?**
A: The thresholds (rise > 0.0145, fall < -0.003 net-transfer-rate) are community-known approximations based on observed FPL price-change behavior. FPL never publishes the formula, so accuracy varies but is usually good for high-confidence (≥0.8) flags.

**Q: Can I get H2H league data?**
A: Not in v1. The classic-league endpoints work for H2H members but the H2H-specific endpoints (matches, knockouts) aren't yet wired. File an issue on the actor page and I'll add it.

**Q: Does the AI verdict cost extra?**
A: Yes, $0.05 per verdict. It's opt-in via `enableAiVerdict: true` in `gameweek_picks` mode only.

**Q: Will this break when FPL changes their API?**
A: The endpoints have been stable since ~2017. If they break, every FPL tool breaks at once — the community pressure forces a quick fix. The actor will continue to fetch what it can and log warnings on partial failures.

### Support

Issue with the actor? Open a ticket on the actor's Apify page — I respond within 48h.

# Actor input Schema

## `mode` (type: `string`):

Pick a workflow. Each mode emits a distinct output row shape — see README for samples and which mode fits your use case.

## `managerIds` (type: `array`):

Your FPL manager ID(s). Find yours in the URL when logged in: fantasy.premierleague.com/entry/<your-id>/event/N. Required for manager\_dashboard. Optional for live\_tracker.

## `leagueIds` (type: `array`):

Mini-league ID(s) — the number in the URL when viewing a league. ID 314 is the Overall global league everyone is in. Required for mini\_league\_intel.

## `gameweek` (type: `integer`):

Which gameweek to analyze. If omitted, defaults to the current/next gameweek. Required for live\_tracker.

## `picksTopN` (type: `integer`):

gameweek\_picks mode. Top-N candidates per category (captain / transfer-in / differential / sell).

## `picksDifferentialThresholdPct` (type: `number`):

gameweek\_picks mode. Max global ownership %% for a player to qualify as a differential.

## `picksFixtureLookahead` (type: `integer`):

gameweek\_picks mode. How many upcoming fixtures to weight in the difficulty score.

## `optimizerBudget` (type: `number`):

wildcard\_optimizer mode. Total squad budget in £m. Default 100.0 is the FPL game default.

## `optimizerLockedPlayers` (type: `array`):

wildcard\_optimizer mode. FPL element IDs the optimizer must include in the final squad (e.g. 430 for Haaland). Use this to force premium picks.

## `optimizerExcludedPlayers` (type: `array`):

wildcard\_optimizer mode. FPL element IDs the optimizer must exclude.

## `optimizerExcludedTeams` (type: `array`):

wildcard\_optimizer mode. FPL team IDs to skip entirely (e.g. a club whose fixtures are too tough).

## `leagueTopManagersPerLeague` (type: `integer`):

mini\_league\_intel mode. How many top-ranked managers per league to fetch + analyze. Larger = slower + more cost.

## `leagueCompareToManagerId` (type: `string`):

mini\_league\_intel mode. Optional. Your manager ID to compute your-vs-the-field deltas (captain match, differentials you have/miss).

## `priceMinConfidence` (type: `number`):

price\_change\_predictor mode. Only emit predictions with at least this confidence (0..1).

## `priceIncludeNeutral` (type: `boolean`):

price\_change\_predictor mode. If true, emit a row for every player even if no change predicted (useful for raw transfer data).

## `liveRefreshIntervalSec` (type: `integer`):

live\_tracker mode. If > 0, poll this many seconds between snapshots until maxSnapshots is reached. 0 = single snapshot.

## `liveMaxSnapshots` (type: `integer`):

live\_tracker mode. Cap on snapshots even if refreshIntervalSec > 0. Each snapshot fires a billable live-snapshot event.

## `historicalSeasons` (type: `array`):

historical\_seasons mode. FPL seasons in YYYY-YY format (e.g. '2024-25'). Pass 'all' for all 10 archived seasons. Tier note: 2021-22+ has full xG data; 2016-17 to 2017-18 are basic stats only.

## `historicalDataType` (type: `string`):

historical\_seasons mode. What to pull. per\_gameweek is the heaviest (~600 rows × N gameweeks per season).

## `historicalGameweeksFilter` (type: `array`):

historical\_seasons mode. Optional. Limit to specific gameweeks (e.g. \['1','2','3']). Empty = all 38.

## `enableAiVerdict` (type: `boolean`):

Adds a 1-paragraph 'manager's brief' (captain rec + reasoning + sell candidates) using Gemini 2.5 Flash. Costs +$0.05 per verdict event. Available in gameweek\_picks mode.

## `maxItems` (type: `integer`):

Hard cap on output rows for safety. Tune up for historical seasons mode (a single season has ~600 rows × 38 GWs = 22,800 rows).

## Actor input object example

```json
{
  "mode": "gameweek_picks",
  "managerIds": [
    "1000000"
  ],
  "leagueIds": [
    "314"
  ],
  "picksTopN": 5,
  "picksDifferentialThresholdPct": 5,
  "picksFixtureLookahead": 3,
  "optimizerBudget": 100,
  "leagueTopManagersPerLeague": 50,
  "priceMinConfidence": 0.5,
  "priceIncludeNeutral": false,
  "liveRefreshIntervalSec": 0,
  "liveMaxSnapshots": 1,
  "historicalSeasons": [
    "2024-25"
  ],
  "historicalDataType": "per_gameweek",
  "enableAiVerdict": false,
  "maxItems": 1000
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing all output rows. Filter by 'type' field to isolate captain\_picks, optimizer\_squads, league\_summaries, price\_change\_predictions, manager\_dashboards, live\_snapshots, historical\_player\_gw, ai\_verdicts, etc.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "managerIds": [
        "1000000"
    ],
    "leagueIds": [
        "314"
    ],
    "historicalSeasons": [
        "2024-25"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("constructive_calm/fpl-intelligence").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "managerIds": ["1000000"],
    "leagueIds": ["314"],
    "historicalSeasons": ["2024-25"],
}

# Run the Actor and wait for it to finish
run = client.actor("constructive_calm/fpl-intelligence").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "managerIds": [
    "1000000"
  ],
  "leagueIds": [
    "314"
  ],
  "historicalSeasons": [
    "2024-25"
  ]
}' |
apify call constructive_calm/fpl-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=constructive_calm/fpl-intelligence",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "FPL Intelligence - Picks, Optimizer, Watchlist, History",
        "description": "Fantasy Premier League intelligence: weekly captain & transfer picks, wildcard optimizer, mini-league insights, price-change predictor, manager dashboard, live tracker, 10 seasons of history.",
        "version": "1.0",
        "x-build-id": "0qc4uRP54F3Rd8wsS"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/constructive_calm~fpl-intelligence/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-constructive_calm-fpl-intelligence",
                "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/constructive_calm~fpl-intelligence/runs": {
            "post": {
                "operationId": "runs-sync-constructive_calm-fpl-intelligence",
                "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/constructive_calm~fpl-intelligence/run-sync": {
            "post": {
                "operationId": "run-sync-constructive_calm-fpl-intelligence",
                "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",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "What do you want to do?",
                        "enum": [
                            "gameweek_picks",
                            "wildcard_optimizer",
                            "mini_league_intel",
                            "price_change_predictor",
                            "manager_dashboard",
                            "live_tracker",
                            "historical_seasons"
                        ],
                        "type": "string",
                        "description": "Pick a workflow. Each mode emits a distinct output row shape — see README for samples and which mode fits your use case.",
                        "default": "gameweek_picks"
                    },
                    "managerIds": {
                        "title": "Manager IDs",
                        "type": "array",
                        "description": "Your FPL manager ID(s). Find yours in the URL when logged in: fantasy.premierleague.com/entry/<your-id>/event/N. Required for manager_dashboard. Optional for live_tracker.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "leagueIds": {
                        "title": "Mini-League IDs",
                        "type": "array",
                        "description": "Mini-league ID(s) — the number in the URL when viewing a league. ID 314 is the Overall global league everyone is in. Required for mini_league_intel.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "gameweek": {
                        "title": "Gameweek (optional)",
                        "minimum": 1,
                        "maximum": 38,
                        "type": "integer",
                        "description": "Which gameweek to analyze. If omitted, defaults to the current/next gameweek. Required for live_tracker."
                    },
                    "picksTopN": {
                        "title": "Picks: how many candidates per category",
                        "minimum": 3,
                        "maximum": 20,
                        "type": "integer",
                        "description": "gameweek_picks mode. Top-N candidates per category (captain / transfer-in / differential / sell).",
                        "default": 5
                    },
                    "picksDifferentialThresholdPct": {
                        "title": "Picks: differential ownership threshold",
                        "minimum": 0.1,
                        "maximum": 25,
                        "type": "number",
                        "description": "gameweek_picks mode. Max global ownership %% for a player to qualify as a differential.",
                        "default": 5
                    },
                    "picksFixtureLookahead": {
                        "title": "Picks: fixture lookahead window",
                        "minimum": 1,
                        "maximum": 8,
                        "type": "integer",
                        "description": "gameweek_picks mode. How many upcoming fixtures to weight in the difficulty score.",
                        "default": 3
                    },
                    "optimizerBudget": {
                        "title": "Optimizer: budget (£m)",
                        "minimum": 80,
                        "maximum": 110,
                        "type": "number",
                        "description": "wildcard_optimizer mode. Total squad budget in £m. Default 100.0 is the FPL game default.",
                        "default": 100
                    },
                    "optimizerLockedPlayers": {
                        "title": "Optimizer: locked player IDs",
                        "type": "array",
                        "description": "wildcard_optimizer mode. FPL element IDs the optimizer must include in the final squad (e.g. 430 for Haaland). Use this to force premium picks.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "optimizerExcludedPlayers": {
                        "title": "Optimizer: excluded player IDs",
                        "type": "array",
                        "description": "wildcard_optimizer mode. FPL element IDs the optimizer must exclude.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "optimizerExcludedTeams": {
                        "title": "Optimizer: excluded team IDs",
                        "type": "array",
                        "description": "wildcard_optimizer mode. FPL team IDs to skip entirely (e.g. a club whose fixtures are too tough).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "leagueTopManagersPerLeague": {
                        "title": "League: top-N managers to fetch",
                        "minimum": 5,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "mini_league_intel mode. How many top-ranked managers per league to fetch + analyze. Larger = slower + more cost.",
                        "default": 50
                    },
                    "leagueCompareToManagerId": {
                        "title": "League: your manager ID (for you-vs-field)",
                        "type": "string",
                        "description": "mini_league_intel mode. Optional. Your manager ID to compute your-vs-the-field deltas (captain match, differentials you have/miss)."
                    },
                    "priceMinConfidence": {
                        "title": "Price: min confidence",
                        "minimum": 0,
                        "maximum": 1,
                        "type": "number",
                        "description": "price_change_predictor mode. Only emit predictions with at least this confidence (0..1).",
                        "default": 0.5
                    },
                    "priceIncludeNeutral": {
                        "title": "Price: include neutral signals",
                        "type": "boolean",
                        "description": "price_change_predictor mode. If true, emit a row for every player even if no change predicted (useful for raw transfer data).",
                        "default": false
                    },
                    "liveRefreshIntervalSec": {
                        "title": "Live: refresh interval (seconds)",
                        "minimum": 0,
                        "maximum": 600,
                        "type": "integer",
                        "description": "live_tracker mode. If > 0, poll this many seconds between snapshots until maxSnapshots is reached. 0 = single snapshot.",
                        "default": 0
                    },
                    "liveMaxSnapshots": {
                        "title": "Live: max snapshots",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "live_tracker mode. Cap on snapshots even if refreshIntervalSec > 0. Each snapshot fires a billable live-snapshot event.",
                        "default": 1
                    },
                    "historicalSeasons": {
                        "title": "Historical: seasons",
                        "type": "array",
                        "description": "historical_seasons mode. FPL seasons in YYYY-YY format (e.g. '2024-25'). Pass 'all' for all 10 archived seasons. Tier note: 2021-22+ has full xG data; 2016-17 to 2017-18 are basic stats only.",
                        "items": {
                            "type": "string"
                        },
                        "default": [
                            "2024-25"
                        ]
                    },
                    "historicalDataType": {
                        "title": "Historical: data type",
                        "enum": [
                            "per_gameweek",
                            "season_totals_only",
                            "fixtures_only",
                            "players_only"
                        ],
                        "type": "string",
                        "description": "historical_seasons mode. What to pull. per_gameweek is the heaviest (~600 rows × N gameweeks per season).",
                        "default": "per_gameweek"
                    },
                    "historicalGameweeksFilter": {
                        "title": "Historical: gameweek filter",
                        "type": "array",
                        "description": "historical_seasons mode. Optional. Limit to specific gameweeks (e.g. ['1','2','3']). Empty = all 38.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "enableAiVerdict": {
                        "title": "Enable AI verdict (Gemini)",
                        "type": "boolean",
                        "description": "Adds a 1-paragraph 'manager's brief' (captain rec + reasoning + sell candidates) using Gemini 2.5 Flash. Costs +$0.05 per verdict event. Available in gameweek_picks mode.",
                        "default": false
                    },
                    "maxItems": {
                        "title": "Max output items",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Hard cap on output rows for safety. Tune up for historical seasons mode (a single season has ~600 rows × 38 GWs = 22,800 rows).",
                        "default": 1000
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
