---
title: "Projected captain and FLEX ownership by contest, the biggest prize pool first (lobby), and by contest group"
method: GET
path: "/api/v1/dfs/slates/{slate_id}/contest-ownership"
tags: ["DFS"]
---

# Projected captain and FLEX ownership by contest, the biggest prize pool first (lobby), and by contest group

`GET /api/v1/dfs/slates/{slate_id}/contest-ownership`

## Request

- Base URL: `https://api.stat-api.com`
- URL: `https://api.stat-api.com/api/v1/dfs/slates/{slate_id}/contest-ownership`
- Auth: HTTP bearer

How the learned per-contest ownership of STAT_API_LATEST changes from contest to contest on
one slate.

The lobby (Frank 2026-10-01): `contests` lists every contest of the slate with learned rows,
the biggest prize pool first (then the largest `max_entries`, then the lowest id). The tool
opens on the biggest pool (`default_contest`) and compares each value with the biggest cash
game (`default_compare`, the same order among cash contests). `contest` holds the values of
`?contest=` (default: `default_contest`), `compare` those of `?compare=` (default:
`default_compare`), and `across` the values of contests side by side, in lobby order: with
DFS access the 5 biggest GPP contests and the 5 biggest cash games (the page's three
filters), without it the free contests. An id that is not a contest of the slate answers
400.

The groups stay. The slate's contests fall into groups by kind (cash vs GPP as the operator
labels them: contest_type 1 is cash, every other type GPP; the model's name rule only for a
contest without a type), by entry type inside GPP (single_entry:
1 entry per user, else multi_entry) and by size tier of `max_entries` (2, 3-100, 101-1k,
1k-10k, 10k-100k, 100k+). Qualifiers and cancelled contests are left out, and so is a
contest without learned rows. Each group shows the stored values of ONE real contest, its
representative: a paid contest first (entry fee above 0), then the largest field
(`max_entries`), then the most entries, then the largest prize pool, then the lowest id.
Empty groups are not sent.

Captain (DraftKings CPT, FanDuel MVP) and FLEX are separate projections: a player's captain
row holds his captain share and his FLEX row the rest. Each player shows, per group, both
values, their total, the captain rate (captain / total) and his captain and FLEX ranks in
the group, plus the spread of each slot across the groups. Per slot: salary, projected
points and points per $1,000 from the slate's STAT_API_LATEST projections.

Only persisted learned rows are served (`stats.ownership_model` set,
`_metadata.contest_ownership = persisted`), never STAT_API (2.1) and never a read-time
calibration. A slate without them answers 200 with empty `contests`, `groups` and
`players` and a `reason`.

Access (Frank 2026-10-01, about 22:30Z: "top 5 largest contest types on the left, they
only have access to top 10 ownership of players for single game formats"; Frank
2026-10-02: "add in the biggest 5 contests for both all | cash | gpp - there should be 10
for both DK and FD"; then "make it 5 records throughout the entire system"): with DFS
access (Pro or the DFS add-on) every contest, every player, the groups and the CSV.
Without it (no key, the trial key, a Free key) the free contests only: the 5 biggest prize
pools of the slate, of any kind (fewer on a slate with fewer). `contests` lists only them,
`groups` is empty, each player's `by_group` is empty and his spreads are null. `contest` or `compare` on another contest of the slate
answers 200 with `locked` true, no player and no position total. On a pre-game single-game
slate (DraftKings Showdown, FanDuel single game; never an in-game format) such a caller sees
the featured players: the 5 players with the highest total ownership in any free contest
(`access.plan = featured`). On any other slate the first 5 players (`access.plan =
preview`). Every list of such an answer holds at most 5 records, the record cap of every
non-paid read. One exception (Frank 2026-10-19): the single-game slate of a TNF or MNF game
(an NFL game on a Monday, Wednesday or Thursday, ET) is free in full to every caller, every
contest and every player (`access.plan = primetime`, `x-preview-exempt: primetime-ownership`);
its CSV stays Pro.
A gated answer names the plan in `_metadata` (`required_tier`, `message`,
`total_actual_records`) and in the `x-required-plan` and `x-preview-rows` headers.
Position totals always cover every player of an open contest.

## Path parameters

- `slate_id` integer, required

## Query parameters

- `contest` integer
- `compare` integer
- `format` string
- `csv` string

## Response `200`

Projected captain and FLEX ownership by contest, the biggest prize pool first (lobby), and by contest group

- DFSSlatesContestOwnershipDfsSlateContestOwnershipResponse
  - `_metadata` object, required: Where the values come from, and on a gated answer the plan that opens the rest.
    - `contest_ownership` 'persisted', nullable: persisted (the stored rows of the learned model) when contests are served, else null.
    - `message` string, nullable: Sent only when players or contests are held back - what the plan opens.
    - `required_tier` string, nullable: Sent only when players or contests are held back - pro.
    - `total_actual_records` integer, nullable: Sent only when players or contests are held back - the players on the board.
  - `access` object, required: What this caller sees.
    - `plan` 'pro' | 'primetime' | 'featured' | 'preview', required: pro (every contest and player), primetime (every contest and player for every caller, on a TNF or MNF game's single-game slate), featured (the free contests with the 5 featured players, on a pre-game single-game slate) or preview (the free contests with 5 players).
    - `players_shown` integer, required: Players in `players`.
    - `players_total` integer, required: Players on the board.
  - `across` object, required: The biggest contests side by side (the tool's Across contests tab).
    - `contest_ids` integer[], required: The contests in lobby order. With DFS access the 5 biggest GPP contests and the 5 biggest cash games (the page's three filters); without it the free contests, so the ids of `contests`.
    - `values` object, required: Contest id to player id to [captain_pct, flex_pct], for the open contests of `contest_ids` and the shown players with a value. A locked contest is left out.
  - `as_of` string, nullable: The newest write time of the served rows (ISO 8601, UTC). Null when no rows are served.
  - `compare` object, nullable: The values of the compare contest (`?compare=`, default `default_compare`), the same shape as `contest`. Null when the slate has no cash contest and none is asked.
    - `id` integer, required: dfs.contests id.
    - `locked` boolean, required: True when this caller may not see the contest's values. A locked contest sends no player and no position total.
    - `players` object[], required: The shown players (all with DFS access, else the 5 featured players or the 5-row preview) with a value in the contest, the highest total first. Empty when locked.
      - `captain_pct` number, double, nullable: Captain ownership in the contest, in percent (the stored projected_ownership of the captain row x 100).
      - `captain_rank` integer, nullable: Rank of the captain ownership among all players of the contest (1 = most owned; ties share a rank).
      - `captain_rate` number, double, nullable: captain_pct / total_pct (0-1). Null when the total is 0 or a value is missing.
      - `flex_pct` number, double, nullable: FLEX ownership in the contest, in percent.
      - `flex_rank` integer, nullable: Rank of the FLEX ownership among all players of the contest.
      - `player_id` integer, nullable: nfl.players id (the `player_id` of `players`).
      - `total_pct` number, double, nullable: captain_pct + flex_pct.
    - `position_totals` object, required: The contest's ownership summed by real position over every player of the contest (also the players not shown), in percent. Captain sums to about 100, FLEX to about 100 x flex_seats. Both maps are empty when locked.
      - `captain` object, required: Real position (QB, RB, WR, TE, K, DST, D) to the sum of its captain ownership.
      - `flex` object, required: Real position to the sum of its FLEX ownership.
    - `reason` string, nullable: Why the contest is locked, and the plan that opens it. Null when it is open.
  - `contest` object, nullable: The values of the selected contest (`?contest=`, default `default_contest`). Null without a contest.
    - `id` integer, required: dfs.contests id.
    - `locked` boolean, required: True when this caller may not see the contest's values. A locked contest sends no player and no position total.
    - `players` object[], required: The shown players (all with DFS access, else the 5 featured players or the 5-row preview) with a value in the contest, the highest total first. Empty when locked.
      - `captain_pct` number, double, nullable: Captain ownership in the contest, in percent (the stored projected_ownership of the captain row x 100).
      - `captain_rank` integer, nullable: Rank of the captain ownership among all players of the contest (1 = most owned; ties share a rank).
      - `captain_rate` number, double, nullable: captain_pct / total_pct (0-1). Null when the total is 0 or a value is missing.
      - `flex_pct` number, double, nullable: FLEX ownership in the contest, in percent.
      - `flex_rank` integer, nullable: Rank of the FLEX ownership among all players of the contest.
      - `player_id` integer, nullable: nfl.players id (the `player_id` of `players`).
      - `total_pct` number, double, nullable: captain_pct + flex_pct.
    - `position_totals` object, required: The contest's ownership summed by real position over every player of the contest (also the players not shown), in percent. Captain sums to about 100, FLEX to about 100 x flex_seats. Both maps are empty when locked.
      - `captain` object, required: Real position (QB, RB, WR, TE, K, DST, D) to the sum of its captain ownership.
      - `flex` object, required: Real position to the sum of its FLEX ownership.
    - `reason` string, nullable: Why the contest is locked, and the plan that opens it. Null when it is open.
  - `contests` object[], required: The lobby, the biggest prize pool first, then the largest max_entries, then the lowest id. With DFS access every contest of the slate with learned rows (no qualifier, no cancelled contest). Without it only the free contests: the 5 biggest prize pools of the slate, in the same order. The page filters them All, Cash or GPP and shows 5 of each with DFS access.
    - `entries` integer, required: Entries (entry_count) when last read.
    - `entry_fee` number, double, required: Entry fee, in dollars.
    - `entry_type` 'single_entry' | 'multi_entry', nullable: GPP only: single_entry (max_entries_per_user 1) or multi_entry. Null for cash.
    - `external_id` integer, required: Operator contest ID.
    - `group` string, required: The key of the contest's group in `groups`.
    - `id` integer, required: dfs.contests id (the `contest` and `compare` parameter).
    - `kind` 'cash' | 'gpp', required: cash (contest_type 1) or gpp, the same rule as the groups.
    - `max_entries` integer, required: Maximum entries.
    - `max_entries_per_user` integer, required: Maximum entries per user.
    - `name` string, required: Contest name.
    - `open` boolean, required: True when this caller may see the contest's values. Always true, since a caller without DFS access gets only the free contests.
    - `prize_pool` number, double, required: Prize pool, in dollars.
    - `prize_rank` integer, required: The contest's place among every contest of the slate (1 = the biggest prize pool). A caller without DFS access sees the ranks of the free contests, 1-5 always among them.
    - `same_terms` integer, required: How many other contests of the slate share the model's contest terms (archetype, max_entries, entry fee, max entries per user), so the same values.
    - `tier` '2' | '3-100' | '101-1k' | '1k-10k' | '10k-100k' | '100k+', required: Size tier by max_entries (the tiers of the groups).
  - `default_compare` integer, nullable: The contest each value compares with (Frank 2026-10-01): the biggest cash game (contest_type 1), by prize pool, then max_entries, then id. Null when the slate has no cash contest.
  - `default_contest` integer, nullable: The contest the tool opens on (Frank 2026-10-01): the biggest prize pool, the first of `contests`. Null without a contest.
  - `default_group` string, nullable: The group key the tool opened first before the lobby (Frank 2026-10-01, the largest GPP): the GPP group whose representative contest comes first by the representative order (paid, then the largest max_entries, then entries, prize pool, id). Null without a GPP group.
  - `groups` object[], required: The contest groups, cash first, then single-entry GPP, then multi-entry GPP, each by size tier. DFS access only; empty without it.
    - `contest` object, required: The representative contest, whose stored values the group shows: paid first, then the largest max_entries, then the most entries, then the largest prize pool, then the lowest id.
      - `archetype` 'cash' | 'gpp_single_entry' | 'gpp_small_field' | 'gpp_mme' | 'baseline', required: The stored contest_archetype of its rows, else the model's rule.
      - `contest_id` integer, required: dfs.contests id.
      - `entries` integer, required: Entries (entry_count) when last read.
      - `entry_fee_cents` integer, required: Entry fee in cents.
      - `external_id` integer, required: Operator contest ID.
      - `max_entries` integer, required: Maximum entries (the model's size feature).
      - `max_entries_per_user` integer, required: Maximum entries per user.
      - `name` string, required: Contest name.
      - `prize_pool_cents` integer, required: Prize pool in cents.
    - `contest_count` integer, required: Contests of the slate in this group that have learned rows.
    - `entry_type` 'single_entry' | 'multi_entry', nullable: GPP only: single_entry (max_entries_per_user 1) or multi_entry. Null for cash.
    - `key` string, required: The group key: kind, entry type (GPP only) and size tier, e.g. cash:3-100, gpp:single_entry:1k-10k, gpp:multi_entry:100k+.
    - `kind` 'cash' | 'gpp', required: cash or gpp, as the operator labels the contest (Frank 2026-10-01): contest_type 1 is cash, every other type gpp. A DraftKings Triple Up (contest_type 0) is gpp, although the model's archetype calls it cash. Only a contest without a contest_type falls back to the model's name rule (Double Up, 50/50, H2H, Triple Up).
    - `position_totals` object[], required: The group's ownership summed by real position, captain and FLEX apart, over every player of the representative contest (also the players a preview does not list). Captain sums to about 100, FLEX to about 100 x flex_seats.
      - `captain_pct` number, double, required: Sum of the captain ownership, in percent.
      - `flex_pct` number, double, required: Sum of the FLEX ownership, in percent.
      - `position` string, required: Real position (QB, RB, WR, TE, K, DST on DraftKings, D on FanDuel).
    - `size_tier` '2' | '3-100' | '101-1k' | '1k-10k' | '10k-100k' | '100k+', required: Size tier by max_entries.
  - `model` string, nullable: The learned model label of the served rows (`stats.ownership_model`, e.g. single_hgb@19d12bd6d309). Null when no rows are served.
  - `players` object[], required: The players, highest peak total first (all with DFS access, else the 5 featured players or the 5-row preview). The order is the same for every caller, so the first 5 of a Pro answer are the featured players.
    - `by_group` object[], required: The player's values in each group, in the order of `groups`. Empty without DFS access.
      - `captain_pct` number, double, nullable: Captain ownership in the representative contest, in percent (the stored projected_ownership of the captain row x 100).
      - `captain_rank` integer, nullable: Rank of the captain ownership among all players of the group (1 = most owned; ties share a rank).
      - `captain_rate` number, double, nullable: captain_pct / total_pct (0-1). Null when the total is 0 or a value is missing.
      - `flex_pct` number, double, nullable: FLEX ownership in the representative contest, in percent.
      - `flex_rank` integer, nullable: Rank of the FLEX ownership among all players of the group.
      - `key` string, required: The group key.
      - `total_pct` number, double, nullable: captain_pct + flex_pct.
    - `captain` object, nullable: The captain (CPT or MVP) slot. Null on a format without one.
      - `ceiling` number, double, nullable: The projection's ceiling for this slot, its 85th percentile (the ceiling of GET /api/v1/dfs/slates/{slate_id}/projections).
      - `floor` number, double, nullable: The projection's floor for this slot, its 15th percentile (the floor of GET /api/v1/dfs/slates/{slate_id}/projections).
      - `points_per_1k` number, double, nullable: Projected points per $1,000 of salary.
      - `projected_points` number, double, nullable: STAT_API_LATEST projected fantasy points of this slot.
      - `salary` integer, nullable: Salary of this slot.
      - `slate_player_id` integer, required: dfs.slate_players id of this slot.
    - `captain_spread` object, nullable: Max minus min of the captain ownership across the groups, with the groups at both ends. Null without a value, and always null without DFS access (no groups).
      - `high_group` string, required: The group key with the highest value (the first in group order on a tie).
      - `high_pct` number, double, required: The highest value, in percent.
      - `low_group` string, required: The group key with the lowest value (the first in group order on a tie).
      - `low_pct` number, double, required: The lowest value, in percent.
      - `spread_pct` number, double, required: high_pct minus low_pct.
    - `flex` object, nullable: The FLEX slot.
      - `ceiling` number, double, nullable: The projection's ceiling for this slot, its 85th percentile (the ceiling of GET /api/v1/dfs/slates/{slate_id}/projections).
      - `floor` number, double, nullable: The projection's floor for this slot, its 15th percentile (the floor of GET /api/v1/dfs/slates/{slate_id}/projections).
      - `points_per_1k` number, double, nullable: Projected points per $1,000 of salary.
      - `projected_points` number, double, nullable: STAT_API_LATEST projected fantasy points of this slot.
      - `salary` integer, nullable: Salary of this slot.
      - `slate_player_id` integer, required: dfs.slate_players id of this slot.
    - `flex_spread` object, nullable: The same for the FLEX ownership.
      - `high_group` string, required: The group key with the highest value (the first in group order on a tie).
      - `high_pct` number, double, required: The highest value, in percent.
      - `low_group` string, required: The group key with the lowest value (the first in group order on a tie).
      - `low_pct` number, double, required: The lowest value, in percent.
      - `spread_pct` number, double, required: high_pct minus low_pct.
    - `name` string, nullable: Player name.
    - `peak_total_pct` number, double, nullable: The highest total ownership in any free contest (the 5 biggest prize pools of the slate), in percent. The order of players and the featured pick, the same for every caller.
    - `player_id` integer, nullable: nfl.players id.
    - `position` string, nullable: Real position (QB, RB, WR, TE, K, DST or D).
    - `team` string, nullable: Team abbreviation.
  - `reason` string, nullable: Why `contests` and `groups` are empty (an in-game format, no STAT_API_LATEST source for the format, no learned rows yet, or a slate of another league than NFL, which this board does not serve). Null when contests are served.
  - `slate` object, required: The slate.
    - `captain_slot` string, nullable: The captain slot word of the format (CPT on DraftKings, MVP on FanDuel). Null on a format without one.
    - `external_id` integer, required: Operator slate ID (DraftKings draft group, FanDuel fixture list).
    - `flex_seats` integer, nullable: Roster seats that are not the captain seat, from the slate setting (5 on DraftKings Showdown and on FanDuel single game since 2025). The FLEX ownership of one contest sums to 100 x flex_seats percent.
    - `game_type` 'classic' | 'showdown' | 'single_game' | 'tiers', nullable: The slate setting's format, as on /dfs/slates.
    - `games` object[], required: The slate's games.
      - `away` string, nullable: Away team abbreviation.
      - `game_id` integer, required: nfl.games id.
      - `home` string, nullable: Home team abbreviation.
      - `kickoff` string, nullable: Kickoff (ISO 8601, UTC).
    - `id` integer, required: dfs.slates id.
    - `in_game` boolean, required: True for an in-game format (DraftKings In-Game Showdown, FanDuel 2nd half or 4th quarter). In-game formats have no projections by design.
    - `name` string, nullable: Slate name.
    - `operator` string, required: DraftKings or FanDuel.
    - `start_time` string, nullable: Lock time (ISO 8601, UTC).
    - `status` string, nullable: Upcoming, Live or Completed.
  - `source` 'STAT_API_LATEST', required: The projection source of every value (always STAT_API_LATEST).

## Other responses

- `400`: Invalid slate ID, an unknown format or csv value, csv without format=csv, or a contest or compare id that is not a contest of the slate with learned rows
- `402`: format=csv without DFS access
- `404`: Slate not found (an excluded format, a test or a cancelled slate)

## Changes

- **2026-10-19** `601ff9eaca3f`: 1 warning
  - added the new `primetime` enum value to the `access/plan` response property for the response status `200`
- **2026-10-19** `23b66b957723`: 4 info
  - added the optional property `players/items/captain/ceiling` to the response with the `200` status
  - added the optional property `players/items/captain/floor` to the response with the `200` status
  - added the optional property `players/items/flex/ceiling` to the response with the `200` status
  - added the optional property `players/items/flex/floor` to the response with the `200` status

[Operation history](https://skmtc.dev/stat-api/apis/sports-db-public-api/changes/api/v1/dfs/slates/:slate_id/contest-ownership/get.md)

---

[API](https://skmtc.dev/stat-api/apis/sports-db-public-api.md) · [All operations](https://skmtc.dev/stat-api/apis/sports-db-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/stat-api/apis/sports-db-public-api/revisions/601ff9eaca3f?raw)
