---
title: "Build a ten-player NBA Salary Cap squad from scratch"
method: POST
path: "/v1/fantasy/nba/me/squad-builder"
tags: ["fantasy"]
---

# Build a ten-player NBA Salary Cap squad from scratch

`POST /v1/fantasy/nba/me/squad-builder`

## Request

- Base URL: `https://api.predixsport.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.predixsport.com/v1/fantasy/nba/me/squad-builder`
- Auth: none declared

Returns up to three legal ten-player squads within the budget, at the frozen prices of the official market, with five back court and five front court and at most two players from one club. The budget is the 100.0M cap less the `bank_to_leave` reserve, so it is the cap itself only when no reserve is asked for. Use it at the start of a season, or to see what a clean sheet would look like. It SAVES NO SQUAD: the answer is a proposal, and the owner's own roster only changes when he saves one through PUT /v1/fantasy/nba/me/roster. The valuation is deliberately NOT the weekly rule. At the start of a season that rule's recent form is last season's closing minutes and it ignores the opening price, which already carries the summer. A player with a season record is valued half on what he did and half on what his price implies for his court. A player without one, or with too few games to read as a record, is valued on the price line alone and `valuation_basis` says which of the two it was. At the start of a season that record is LAST season's, because ours holds nothing about a season that has not started, and `season_basis` on each row says which season it came from. Squads are valued over the first two official Gameweeks still ahead: for every Gameday of that window the best legal five of the ten, added up, which is what the game scores. The same ten are held for the whole window and no future transfer is simulated inside it, which is what `window_assumption` says. `window` lists the Gamedays and `gameweeks` on each squad says what each week contributed, so a squad that gives up the first one to win the second is visible. Two Gameweeks is a product default, not a measured optimum. `bank_after` is what is left of the cap with the `reserve` named beside it rather than subtracted from it twice. This call SOLVES rather than reads: three distinct squads over two whole Gameweeks of the full market, each its own exact program. It takes up to about 30 seconds, so give it a client timeout well above that and tell a waiting user what it is doing. `search` says how far the search got and it is three things. 'exact' means every legal squad the budget reaches was compared. 'certified' means it stopped as soon as it could prove it was inside its optimality tolerance, and `search_gap` says how close to the best squad there is every squad here was proved to be, against the `search_gap_tolerance` it was allowed. 'truncated' means the clock ran out before it could prove anything. On anything but 'exact', say so beside the squads and say how many squads came back, because fewer than three is the shape a search that stopped early takes. When our own NBA schedule does not yet cover every Gameday of that window, this answers 409 with the sentence to show the owner rather than valuing a squad over a week it cannot see. `bank_to_leave` keeps money back for later moves. `protected` names players the squad must contain whatever the numbers say. It runs ONLY while the official market is OPEN, which is a Gameday whose deadline is still ahead. Between two seasons the collector still freezes the board the game closed the last one with, and that board names players who have retired since, so this endpoint answers 409 with the sentence to show the owner rather than building a squad out of it. Appends an immutable snapshot and changes nothing else. It never signs in to the NBA game. Owner comes from the bearer token. Requires mcp:read and fantasy:nba:write. The NBA fantasy workspace is a public beta. When the operator narrows it to a private trial, this endpoint answers 403 for an account outside it.

## Headers

- `prefer` string, nullable: Send `respond-async` to get 202 and a job id at once instead of waiting, then read the result at /v1/fantasy/jobs/{job_id}.
- `authorization` string, nullable

## Request body

- NBAFantasySquadRequest
  - `season` string, nullable
  - `bank_to_leave` number: Millions to keep back for later moves. Zero spends it all.
  - `protected` string[]: Players the squad must contain whatever the numbers say.
  - `excluded` string[]: Players to leave out.

## Response `200`

Successful Response

- NBAFantasySquadResponse
  - `sport` 'nba'
  - `mode` 'squad_builder'
  - `snapshot_id` integer, required
  - `season` string, required
  - `preset` string, required
  - `policy_version` string, nullable
  - `champion` string, nullable
  - `court_source` 'official_market'
  - `board_digest` string, required
  - `roster_revision` integer, required
  - `market` NBAFantasyMarketReference, required: Which frozen snapshot of the official market a plan was priced from.
    - `snapshot_id` integer, required
    - `revision` integer, required
    - `period_kind` 'gameday' | 'calendar_day', required
    - `period_key` string, required
    - `source_observed_at` string, date-time, nullable
    - `collected_at` string, date-time, nullable
    - `deadline_at` string, date-time, nullable: The official Gameday deadline this market was frozen before.
    - `player_count` integer, required
    - `priced_players` integer, required: How many priced players we could place against our own player identity. The rest are on the market and not in this plan.
    - `duplicate_identities` integer
  - `budget` number, required
  - `bank_to_leave` number, required
  - `cap` number, required
  - `value_basis` 'fielded_five': Squads are ranked on the five they would field, never on a sum of the ten.
  - `search` 'exact' | 'certified' | 'truncated': 'exact' means every legal squad the budget reaches was compared and these are the best there are. 'certified' means the search stopped as soon as it could prove it was inside its optimality tolerance, and `search_gap` says how close to the best squad there is every squad here was proved to be. 'truncated' means the search ran out of time before it could prove anything, so these are the best reached and not the best there are. On anything but 'exact', say so beside the squads and say how many squads came back.
  - `search_gap` number: How close to the best squad there is every squad here was PROVED to be, as a fraction: 0.004 is four tenths of a percent. Zero on an exact search.
  - `search_gap_tolerance` number: The optimality gap the search was allowed to stop at. The builder takes one because the exact search over two Gameweeks of a full market is slow enough to time out, and a proved half a percent is a better answer than an apology.
  - `window` NBAFantasySquadWindow, required: The Gamedays a squad built from scratch was valued over. The first two official Gameweeks still ahead, from the Gameday calendar and the club games frozen with the market. Two Gameweeks is a product default and not a measured optimum.
    - `days` string[], required
    - `start` string, required
    - `end` string, required
    - `gameweeks` NBAFantasySquadWindowWeek[], required
      - `gameweek` integer, required
      - `days` string[], required
  - `window_days` integer, required: How many Gamedays the squads were valued over.
  - `window_label` string, nullable: The Gameweeks of the window, in words.
  - `window_assumption` string, required: The assumption behind every total here, to repeat beside it: the ten are held for the whole window and no future transfer is simulated inside it.
  - `protected` string[]
  - `excluded` string[]
  - `recommended` NBAFantasyBuiltSquad, required
    - `expected_points` number, required: The five this squad would field on EVERY Gameday of the window, added up. The window is the first two official Gameweeks still ahead and the same ten are held for all of it.
    - `fielded_points` number, required: The same number, named for what it measures.
    - `proxy_points` number, required: The old linear ranking, over all ten. Kept for provenance and decides nothing.
    - `gameweeks` NBAFantasyBuiltSquadGameweek[]: What each Gameweek of the window contributed, so a squad that gives up the first one to win the second is visible rather than averaged away.
      - `gameweek` integer, required
      - `gamedays` integer, required
      - `fielded_points` number, required: What this squad fields over that Gameweek alone.
    - `squad_value` number, required
    - `bank_after` number, required: What is left of the cap after buying these ten, which is what the game prints. The reserve is named beside it and is part of this number, not subtracted from it twice.
    - `reserve` number: Millions the owner asked us to keep back.
    - `squad` NBAFantasyBuiltSquadRow[], required
      - `player_name` string, required
      - `court` 'BC' | 'FC', required
      - `team_code` string, required
      - `price` number, required
      - `expected_points` number, required
      - `window_games` integer: How many Gamedays of the window his club plays. It is what makes a cheap tenth man legible: either he covers a night the five do not, or nothing cheaper was legal.
      - `valuation_basis` string, nullable: season_price_blend_v1 blends what he did last season with what his price implies for his court. price_line_v1 is the price alone, which is all we have for a player with no season record.
      - `season_basis` string, nullable: Which season the record behind this player's value came from. At the start of a season it is LAST season's, because nothing has been played in this one yet.
  - `alternatives` NBAFantasyBuiltSquad[]
    - `expected_points` number, required: The five this squad would field on EVERY Gameday of the window, added up. The window is the first two official Gameweeks still ahead and the same ten are held for all of it.
    - `fielded_points` number, required: The same number, named for what it measures.
    - `proxy_points` number, required: The old linear ranking, over all ten. Kept for provenance and decides nothing.
    - `gameweeks` NBAFantasyBuiltSquadGameweek[]: What each Gameweek of the window contributed, so a squad that gives up the first one to win the second is visible rather than averaged away.
      - `gameweek` integer, required
      - `gamedays` integer, required
      - `fielded_points` number, required: What this squad fields over that Gameweek alone.
    - `squad_value` number, required
    - `bank_after` number, required: What is left of the cap after buying these ten, which is what the game prints. The reserve is named beside it and is part of this number, not subtracted from it twice.
    - `reserve` number: Millions the owner asked us to keep back.
    - `squad` NBAFantasyBuiltSquadRow[], required
      - `player_name` string, required
      - `court` 'BC' | 'FC', required
      - `team_code` string, required
      - `price` number, required
      - `expected_points` number, required
      - `window_games` integer: How many Gamedays of the window his club plays. It is what makes a cheap tenth man legible: either he covers a night the five do not, or nothing cheaper was legal.
      - `valuation_basis` string, nullable: season_price_blend_v1 blends what he did last season with what his price implies for his court. price_line_v1 is the price alone, which is all we have for a player with no season record.
      - `season_basis` string, nullable: Which season the record behind this player's value came from. At the start of a season it is LAST season's, because nothing has been played in this one yet.
  - `counts` object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/predixsport/apis/predixsport-api.md) · [All operations](https://skmtc.dev/predixsport/apis/predixsport-api/llms.txt) · [OpenAPI document](https://skmtc.dev/predixsport/apis/predixsport-api/revisions/026afdfa7802?raw)
