Developers

BlueChip Fantasy API

A free, read-only JSON API over BlueChip Fantasy league data, for college and NFL fantasy leagues.

Base URL
https://api.playbluechip.com/v1

Quick start

No sign-up and no key. Every endpoint is a plain GET, so you can try it from a terminal or a browser.

# The current college week and season
curl https://api.playbluechip.com/v1/state/college

# Look up a user, then their leagues this season
curl https://api.playbluechip.com/v1/user/scotty
curl https://api.playbluechip.com/v1/user/$USER_ID/leagues/college/2026

# Rosters and this week's matchups for one league
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/rosters
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/matchups/9

Authentication

None. The API is keyless: no API key, token or header is required, and responses never depend on who is asking. Every league on BlueChip is readable.

Conventions

  • Methods: GET and HEAD only. OPTIONS answers CORS preflight. Anything else returns 405.
  • Bodies: bare JSON with no envelope.
  • Sports: {sport} is college or nfl. It names the calendar a league scores on. College leagues use college. NFL and Devy leagues use nfl: a Devy league stashes college players but scores NFL players. A C2C pair is two linked leagues, and each half uses its own calendar: the college half college, the NFL half nfl.
  • Player ids are source-qualified strings, because college and NFL ids overlap: "college:48213", "nfl:4034". NFL players also carry sleeper_id in the players list.
  • Roster ids are integers 1..N within a league and never change.
  • League, user and draft ids are UUIDs. A value that isn't a UUID returns 404 with body null.
  • League endpoints describe the league's current season.
  • CORS: Access-Control-Allow-Origin: *, so browser apps can call the API directly. Preflight allows one non-simple request header, If-None-Match; ETag, X-BlueChip-As-Of, X-RateLimit-Limit, X-RateLimit-Remaining and Retry-After are readable from script.
  • Compression: send Accept-Encoding: gzip. Responses of 1 KB or more are gzipped.

Caching and freshness

Each response is built on request and cached briefly. Every successful response carries:

HeaderMeaning
ETagStrong validator for the body.
X-BlueChip-As-OfWhen the body was built (ISO 8601).
Last-ModifiedThe same time, in HTTP date format.
Cache-Controlpublic, max-age=<left>, s-maxage=<left>, stale-while-revalidate=<2 × left>, where <left> is the seconds remaining of the body's freshness.

Send If-None-Match: <etag> and you get 304 Not Modified with no body when nothing changed. Please do this, especially for the players lists.

A 404 is cached for 60 seconds (max-age=60), so a league requested just before it was created can keep returning 404 for up to a minute. Error responses (400, 405, 429, 500, 503) carry Cache-Control: no-store.

Freshness by endpoint, in seconds:

EndpointFresh for
/state300
/players/{sport}3600
/players/{sport}/trending300
/user/{user_ref}600
/user/.../leagues300
/user/.../drafts600
/league/{league_id}300
/league/{league_id}/rosters60
/league/{league_id}/users300
/league/{league_id}/matchups/{week}60 while live, 3600 once final
/league/{league_id}/transactions/{round}120
traded_picks300
Drafts30 live, 120 not started, 600 done
Draft picks15 live, 60 not started, 3600 done

Rate limits

  • 1,000 requests per minute per IP, in fixed one-minute windows.
  • Every response after the method check carries X-RateLimit-Limit and X-RateLimit-Remaining.
  • Over the limit you get 429 with code rate_limited and Retry-After (seconds until the window resets).
  • 30 cache misses per minute per IP. Requests that miss the server's cache (the first request for a document, or the first after its copy goes stale) also count toward this second, smaller limit. Over it you get 429 with code too_many_uncached and Retry-After. The X-RateLimit-* headers report only the 1,000-request limit, not this one. A client walking many leagues, users or drafts hits this limit first.
  • Separately, the service caps how much fresh data it builds at once. When it's at capacity, requests that miss the server's cache get 503 with code busy and Retry-After: 5. Responses already in the cache are normally unaffected. Back off and retry.

Using the API responsibly

This API is free and keyless, and it stays that way only if clients are polite. Please:

  • Fetch /players/{sport} at most once per day. It's several MB and changes slowly. Keep a local copy and look players up by player_id.
  • Revalidate instead of re-downloading. Store each response's ETag and send it back as If-None-Match. A 304 Not Modified has no body, so it saves bandwidth on both ends. It still counts toward the per-minute limit, and once the server's copy has gone stale it can count as a cache miss even when the answer is 304.
  • Respect Cache-Control. Don't request the same URL again before its max-age runs out; you'd get the same body. X-BlueChip-As-Of tells you how old it is.
  • Cache league data on your side. Settings, users and finished weeks rarely change. Poll rosters and live matchups no more than once a minute, and finished matchups and drafts rarely.
  • Spread out bulk crawls. Walking many leagues, users or drafts is mostly cache misses; keep it under 30 such requests a minute per IP.
  • Back off on 429 and 503. Wait at least the Retry-After seconds before retrying, and add jitter if you run many workers. Don't retry in a tight loop.
  • Watch X-RateLimit-Remaining and slow down as it nears zero. It tracks only the 1,000-request limit, so also watch for too_many_uncached.

Errors

StatusBodyWhen
304noneIf-None-Match matched.
400{"error": {"code", "message"}}Invalid path or query value.
404nullUnknown path; no such league, user or draft; or, on the user leagues and drafts endpoints, a season other than the current or previous one.
405{"error": {"code": "method_not_allowed", ...}}Not GET, HEAD or OPTIONS.
429{"error": {"code": "rate_limited", ...}}Over 1,000 requests a minute from one IP. Honour Retry-After.
429{"error": {"code": "too_many_uncached", ...}}Over 30 cache misses a minute from one IP. Honour Retry-After.
500{"error": {"code": "internal", "message": "Something went wrong."}}Server error.
503{"error": {"code": "busy", ...}}The service is at capacity. Honour Retry-After.

400 codes: invalid_sport, invalid_type, invalid_limit, invalid_season, invalid_week, invalid_round.

{"error": {"code": "invalid_week", "message": "week must be an integer from 1 to 18."}}

Endpoints

State

Current week and season

GET/v1/state/{sport}

The current week and season for a calendar.

ParamInValues
sportpathcollege or nfl: the calendar a league scores on.
Request
curl https://api.playbluechip.com/v1/state/college
Response
{
  "sport": "college",
  "week": 9,
  "leg": 9,
  "display_week": 9,
  "season": "2026",
  "league_season": "2026",
  "league_create_season": "2026",
  "previous_season": "2025",
  "season_type": "regular",
  "season_start_date": "2026-08-29"
}
  • season_type is pre, regular or off.

Players

All players

GET/v1/players/{sport}

Every player in the pool, keyed by player_id. This is several MB: fetch it at most once a day, use gzip and send If-None-Match.

ParamInValues
sportpathcollege or nfl: the calendar a league scores on.
Request
curl --compressed https://api.playbluechip.com/v1/players/college
Response
{
  "college:48213": {
    "player_id": "college:48213",
    "source_id": "48213",
    "sport": "college",
    "first_name": "Jane",
    "last_name": "Doe",
    "full_name": "Jane Doe",
    "search_first_name": "jane",
    "search_last_name": "doe",
    "search_full_name": "janedoe",
    "position": "WR",
    "fantasy_positions": [
      "WR"
    ],
    "team": "UGA",
    "school": "Georgia",
    "number": 4,
    "class": "SO",
    "height": "72",
    "weight": "190",
    "active": true,
    "status": "Active"
  }
}
  • Identity only: no stats, injury designations, depth charts, projections, ADP or vendor ids.
  • College players have school and class; team is the school's abbreviation. NFL players have college, years_exp, age, birth_date and sleeper_id.
  • status is Active or Inactive for college players. For NFL players it is the NFL roster status, such as Active or Injured Reserve; game-week injury designations and injury details are not returned.

Users

User

GET/v1/user/{user_ref}

A user by username or by user_id.

ParamInValues
user_refpathA username (case-insensitive; letters, digits, _ . -, up to 40 characters) or a user UUID.
Request
curl https://api.playbluechip.com/v1/user/scotty
Response
{
  "user_id": "8b0c...",
  "username": "scotty",
  "display_name": "scotty",
  "avatar": "https://...",
  "is_bot": false
}
  • display_name equals username. avatar is a full image URL. No email or account data is ever returned.

User's leagues

GET/v1/user/{user_id}/leagues/{sport}/{season}

The user's leagues (owned or co-owned) on that calendar whose current season is season, up to 25. Returns an array of League objects.

ParamInValues
user_idpathUser UUID.
sportpathcollege or nfl: the calendar a league scores on.
seasonpathThe calendar's current or previous season (see /state/{sport}). Any other year from 2000 to 2100 returns 404 with null; a value outside that range returns 400.
Request
curl https://api.playbluechip.com/v1/user/$USER_ID/leagues/college/2026

User's drafts

GET/v1/user/{user_id}/drafts/{sport}/{season}

Drafts in that season across up to 25 of the user's leagues on that calendar. Returns an array of Draft objects.

ParamInValues
user_idpathUser UUID.
sportpathcollege or nfl: the calendar a league scores on.
seasonpathThe calendar's current or previous season (see /state/{sport}). Any other year from 2000 to 2100 returns 404 with null; a value outside that range returns 400.
Request
curl https://api.playbluechip.com/v1/user/$USER_ID/drafts/college/2026

Leagues

League

GET/v1/league/{league_id}

A league's settings for its current season.

ParamInValues
league_idpathLeague UUID.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID
Response
{
  "league_id": "d93f52c8-...",
  "name": "Gang's All Here",
  "sport": "college",
  "season": "2026",
  "season_type": "regular",
  "status": "in_season",
  "total_rosters": 12,
  "roster_positions": [
    "QB",
    "RB",
    "RB",
    "WR",
    "WR",
    "TE",
    "FLEX",
    "SUPER_FLEX",
    "BN",
    "BN"
  ],
  "scoring_settings": {
    "rec": 1,
    "pass_yd": 0.04
  },
  "settings": {
    "type": 2,
    "num_teams": 12,
    "start_week": 1,
    "playoff_week_start": 12,
    "waiver_type": 2,
    "waiver_budget": 100,
    "leg": 9,
    "last_scored_leg": 8
  },
  "metadata": {
    "league_type": "CFF_DYNASTY",
    "player_pool": "...",
    "matchup_style": "head_to_head",
    "claim_mechanism": "faab"
  },
  "previous_league_id": null,
  "draft_id": "1f0e...",
  "avatar": null,
  "bracket_id": null,
  "loser_bracket_id": null
}
  • status is pre_draft, drafting, in_season or complete.
  • sport follows the league type: a CFF_* or C2C_COLLEGE* league is college; an NFL_*, DEVY or C2C_NFL* league is nfl.
  • settings values are integers, including rs_slots, devy_slots and, when set, season_acquisition_limit and matchup_acquisition_limit. type is 0 redraft, 2 dynasty. waiver_type is 0 rolling, 1 reverse standings, 2 FAAB; waiver_budget and waiver_bid_min appear only in FAAB leagues.
  • scoring_settings uses common fantasy stat keys where one exists and BlueChip stat names otherwise.
  • metadata values are strings, each present only when set: league_type (CFF_REDRAFT, CFF_DYNASTY, CFF_BEST_BALL, DEVY, C2C_COLLEGE, C2C_COLLEGE_BEST_BALL, C2C_NFL, C2C_NFL_BEST_BALL, NFL_REDRAFT, NFL_DYNASTY or NFL_BEST_BALL), player_pool, matchup_style, consolation_mode, claim_mechanism, trade_deadline_at, trade_review_type, c2c_link_id, c2c_partner_league_id, division_1..N.

Rosters

GET/v1/league/{league_id}/rosters

Every roster in the league.

ParamInValues
league_idpathLeague UUID.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/rosters
Response
[
  {
    "roster_id": 1,
    "league_id": "d93f52c8-...",
    "owner_id": "8b0c...",
    "co_owners": null,
    "players": [
      "college:48213",
      "college:51002"
    ],
    "starters": [
      "college:48213",
      "0"
    ],
    "reserve": [],
    "taxi": [],
    "rs": [],
    "devy": [],
    "settings": {
      "wins": 6,
      "losses": 2,
      "ties": 0,
      "fpts": 1012,
      "fpts_decimal": 44,
      "fpts_against": 950,
      "fpts_against_decimal": 10,
      "total_moves": 14,
      "waiver_position": 3,
      "division": 1
    },
    "metadata": {
      "team_name": "Dawg Pound",
      "roster_uuid": "..."
    }
  }
]
  • starters lines up with the league's starting roster_positions; "0" is an empty slot. reserve is IR, rs is BlueChip redshirt slots, devy is the Devy stash.
  • metadata also carries avatar_url and c2c_pair_id when set.
  • FAAB spending isn't published, so settings has no waiver_budget_used.

League users

GET/v1/league/{league_id}/users

Owners, co-owners and commissioners.

ParamInValues
league_idpathLeague UUID.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/users
Response
[
  {
    "user_id": "8b0c...",
    "username": "scotty",
    "display_name": "scotty",
    "avatar": null,
    "is_bot": false,
    "league_id": "d93f52c8-...",
    "is_owner": true,
    "metadata": {
      "team_name": "Dawg Pound"
    }
  }
]
  • is_owner means commissioner or co-commissioner.

Matchups

GET/v1/league/{league_id}/matchups/{week}

One row per roster for a week.

ParamInValues
league_idpathLeague UUID.
weekpath1 to 13 for leagues on the college calendar, 1 to 18 on the nfl calendar (see sport on the league).
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/matchups/9
Response
[
  {
    "roster_id": 1,
    "matchup_id": 1,
    "points": 112.4,
    "custom_points": null,
    "starters": [
      "college:48213"
    ],
    "players": [
      "college:48213",
      "college:51002"
    ]
  }
]
  • Opponents share a matchup_id; it's null for a bye or a total-points league.
  • For a week that hasn't started, starters is []: lineups set ahead of time stay private until the week begins. Pairings and players are still returned.
  • Per-player points (starters_points, players_points) are not currently returned.

Transactions

GET/v1/league/{league_id}/transactions/{round}

Completed moves for one week of the current season, newest first. Pending waiver claims and unaccepted trades are never returned.

ParamInValues
league_idpathLeague UUID.
roundpathWeek, 1 to 25.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/transactions/9
Response
[
  {
    "transaction_id": "...",
    "type": "waiver",
    "status": "complete",
    "status_updated": 1792800000000,
    "created": 1792800000000,
    "creator": "8b0c...",
    "leg": 9,
    "roster_ids": [
      1
    ],
    "consenter_ids": [
      1
    ],
    "adds": {
      "college:51002": 1
    },
    "drops": {
      "college:40001": 1
    },
    "draft_picks": [],
    "waiver_budget": [],
    "settings": null,
    "metadata": null
  }
]
  • type is free_agent, waiver or trade. Commissioner moves aren't published. Times are epoch milliseconds.
  • settings is always null: waiver bid amounts aren't published.
  • A week holds the moves made after the previous week was scored, up to this week's scoring, so waivers that run after week 8 is scored appear under week 9. Moves since the last scored week appear under the next week.

Traded picks

GET/v1/league/{league_id}/traded_picks

Unused picks now owned by a roster other than the original.

ParamInValues
league_idpathLeague UUID.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/traded_picks
Response
[
  {
    "season": "2027",
    "round": 1,
    "roster_id": 4,
    "previous_owner_id": 4,
    "owner_id": 9,
    "draft_category": "devy",
    "draft_id": null
  }
]
  • draft_category is primary, devy, rookie, supplemental, rookie_supplemental or null.

Drafts

League drafts

GET/v1/league/{league_id}/drafts

Every draft for the league, newest first. Returns an array of Draft objects.

ParamInValues
league_idpathLeague UUID.
Request
curl https://api.playbluechip.com/v1/league/$LEAGUE_ID/drafts

Draft

GET/v1/draft/{draft_id}

One draft.

ParamInValues
draft_idpathDraft UUID.
Request
curl https://api.playbluechip.com/v1/draft/$DRAFT_ID
Response
{
  "draft_id": "1f0e...",
  "league_id": "d93f52c8-...",
  "season": "2026",
  "season_type": "regular",
  "sport": "college",
  "type": "snake",
  "status": "complete",
  "start_time": 1786600000000,
  "created": 1785600000000,
  "last_picked": 1786610000000,
  "settings": {
    "teams": 12,
    "rounds": 25,
    "pick_timer": 90
  },
  "metadata": {
    "name": "...",
    "draft_category": "primary"
  },
  "draft_order": {
    "8b0c...": 1
  },
  "slot_to_roster_id": {
    "1": 1
  },
  "creators": null
}
  • status is pre_draft, drafting, paused or complete.
  • last_picked is when the draft finished, and null until then.

Draft picks

GET/v1/draft/{draft_id}/picks

Picks made so far, in order.

ParamInValues
draft_idpathDraft UUID.
Request
curl https://api.playbluechip.com/v1/draft/$DRAFT_ID/picks
Response
[
  {
    "draft_id": "1f0e...",
    "pick_no": 1,
    "round": 1,
    "draft_slot": 1,
    "roster_id": 1,
    "picked_by": "8b0c...",
    "player_id": "college:48213",
    "is_keeper": null,
    "auto_picked": false,
    "metadata": {
      "first_name": "Jane",
      "last_name": "Doe",
      "position": "WR",
      "team": "UGA",
      "draft_category": "primary"
    }
  }
]

Draft traded picks

GET/v1/draft/{draft_id}/traded_picks

Every pick in that draft that changed hands, used or not. Same shape as league traded picks.

ParamInValues
draft_idpathDraft UUID.
Request
curl https://api.playbluechip.com/v1/draft/$DRAFT_ID/traded_picks

Response shape

  • Player ids are "college:<id>" or "nfl:<id>".
  • One league_id covers every season of a league.
  • No previous_league_id, brackets, or per-player matchup points.
  • Rosters include rs and devy arrays, and settings include redshirt and Devy slots.
  • The user leagues and drafts endpoints serve only the current and previous season, up to 25 leagues.
  • No waiver bid amounts: transaction settings is null and rosters have no waiver_budget_used.
  • Trending includes a trade list and the pct and eligible_leagues fields; lookback_hours is ignored.
  • Every error except a missing resource (400, 405, 429, 500, 503) carries a JSON error object; a missing resource is 404 with null.

Never returned

Emails and auth data, payments, chat, invite codes, pending waiver claims and unaccepted trades, waiver bid amounts and each roster's FAAB spending, lineup plans (a week's starters before it begins), draft queues, watchlists, rankings, notifications, transaction notes, and licensed provider data (stats, injury designations and details, depth charts, news, projections, ADP, vendor ids).

Health

GET https://api.playbluechip.com/health returns {"ok": true}. It is not under /v1 and isn't rate limited.

Building something with the API, or need data it doesn't serve? Tell us on Discord or through Support.