Developers
a rest api over the same thing the app is: scoring systems you write yourself, leagues run under them, and the boards that come out. built for ai tools and external apps, so every answer is json and every id you get back is an id you can send.
v1.0.0 · https://sicko-fantasy.com/api/v1
Auth
one header. make a key on your account page, copy it when it is shown (it is shown once, and is not stored), and send it as a bearer token.
curl https://sicko-fantasy.com/api/v1/me \ -H "Authorization: Bearer sk_sicko_..."
a key acts as the account that made it and can do exactly what that account can do: its own systems, its own leagues, the teams it runs. a key is never an admin, so a league you are not in stays readable and unwritable. revoke one from the same page and it stops working on the next request.
Two tiers
everything for building and running your own leagues: create scoring systems, create leagues, read standings and matchups, set lineups, add and drop, file waiver claims, propose and answer trades, import from sleeper and sync.
60 requests a minute per key
the expensive half: ranked boards with points above average starter, balance scorecards, two systems compared player by player, bench points, and the lineup optimizer for any set of players under any rules. these score a whole season on every call, which is why they are the ones behind a plan.
600 requests a minute per key
pro is granted by hand right now, on the account rather than the key. if you are building something and want it, say so. a free key on a pro endpoint gets 402 with {"error":"pro_plan_required"}, not a silent empty answer.
Rate limits
a fixed window of 60 seconds, counted per key. every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, so you can pace from any response rather than only from the ones that worked. over the line is a 429 with Retry-After in whole seconds.
Errors
every failure is the same two fields. error is a stable code to branch on; message is the sentence a person reads, and it is the league's own wording, so a refused signing says which team already has him.
{ "error": "conflict", "message": "Kyler Murray is already rostered by Team 3" }Endpoints
paths are relative to https://sicko-fantasy.com/api/v1. the machine-readable version is openapi.json, which needs no key and is what to point a tool at.
meta
the key, the plan, and the spec.
GET/openapi.jsonno keyThis document.
GET/mefreeWho this key is, what plan it is on, and how much of the minute is left.
scoring systems
the rules a season is scored under.
GET/systemsfreeThe scoring systems this key can see: the builtin templates plus your own.
POST/systemsfreeCreate a scoring system from a rules object.
GET/systems/{id}freeOne scoring system, with its rules. Reading any system is open.
PATCH/systems/{id}freeRename, redescribe or re-rule a system you own. Builtins refuse an edit from everyone.
DELETE/systems/{id}freeDelete a system you own. A system a league is playing under cannot be deleted.
players
players and team defenses, optionally scored.
GET/playersfreeSearch players and team defenses, optionally scored under a system.
leagues
leagues, standings, matchups, sleeper import.
GET/leaguesfreeThe leagues this key is in: the ones it created, and the ones it runs a team in.
POST/leaguesfreeCreate a league, its teams and a regular-season schedule.
POST/leagues/import/sleeperfreeImport a Sleeper league, or preview what an import would create.
GET/leagues/{id}freeA league, its teams, its standings and the week it is on.
GET/leagues/{id}/matchupsfreeA league's scored games. A bye has a null away side and no winner.
POST/leagues/{id}/syncfreePull a linked league back into line with Sleeper.
teams
rosters and lineups.
GET/leagues/{id}/teams/{teamId}freeA team's roster and its lineup for a week.
PUT/leagues/{id}/teams/{teamId}/lineupfreeSet who starts: the whole card, or one slot at a time.
POST/leagues/{id}/teams/{teamId}/lineup/bestfreeStart the best legal lineup for a week, by what those players actually scored.
POST/leagues/{id}/teams/{teamId}/rosterfreeSign a free agent, drop a player, or swap one for another.
waivers
claims, filed and settled.
GET/leagues/{id}/teams/{teamId}/waiversfreeThis team's waiver claims, newest first.
POST/leagues/{id}/teams/{teamId}/waiversfreeFile a waiver claim. The league has to be on waivers.
GET/leagues/{id}/waiversfreeEvery waiver claim in a league, newest first. The transactions list, as data.
DELETE/leagues/{id}/waivers/{claimId}freeWithdraw a pending claim. It is cancelled, not deleted.
trades
offers between two teams.
GET/leagues/{id}/tradesfreeA league's trades, newest first.
POST/leagues/{id}/tradesfreeOffer a trade. Both sides must be non-empty.
GET/leagues/{id}/trades/{tradeId}freeOne trade.
POST/leagues/{id}/trades/{tradeId}freeAccept, reject or cancel a trade.
analysis
rankings, balance, comparison, the optimizer.
GET/leagues/{id}/teams/{teamId}/bench-pointsproWhat the bench was worth: actual against the best legal lineup of the same roster. Pro.
GET/analysis/rankingsproA ranked board under any scoring system, with positional value. Pro.
GET/analysis/balanceproIs a scoring system balanced across positions? Pro.
GET/analysis/compareproThe same players ranked under two scoring systems. Pro.
POST/optimizeproThe best legal lineup for a set of players. Pro.
Worked examples
write a scoring system
a system is data: weights per stat, bracket tiers, per-position overrides. the whole catalog of scoreable stats is on the systems page.
curl -X POST https://sicko-fantasy.com/api/v1/systems \
-H "Authorization: Bearer $SICKO_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "coverage db",
"rules": {
"global": { "weights": { "rec_yards": 0.1, "rec_tds": 6 } },
"positionOverrides": {
"DB": { "weights": { "cov_yards": -0.25, "def_interceptions": 6 } }
}
}
}'start a league and set a lineup
curl -X POST https://sicko-fantasy.com/api/v1/leagues \
-H "Authorization: Bearer $SICKO_KEY" -H "Content-Type: application/json" \
-d '{ "name": "sicko test", "season": 2025, "scoringSystemId": "db-team-defense",
"teamCount": 10, "acquisitionMode": "waivers" }'
# the whole card at once, one entry per slot, null for an empty one
curl -X PUT "https://sicko-fantasy.com/api/v1/leagues/LEAGUE/teams/TEAM/lineup?week=3" \
-H "Authorization: Bearer $SICKO_KEY" -H "Content-Type: application/json" \
-d '{ "slots": ["00-0036389", null, "DST_SF"] }'optimize a lineup pro
name a league team and it takes that roster, those rules, that season and those slots. or send your own players, your own rules and your own slots and optimize anything at all. the answer is exact, not greedy.
curl -X POST https://sicko-fantasy.com/api/v1/optimize \
-H "Authorization: Bearer $SICKO_KEY" -H "Content-Type: application/json" \
-d '{ "leagueId": "sicko-test", "teamId": "TEAM", "week": 7 }'
# ...or anything at all
curl -X POST https://sicko-fantasy.com/api/v1/optimize \
-H "Authorization: Bearer $SICKO_KEY" -H "Content-Type: application/json" \
-d '{ "systemId": "db-team-defense", "season": 2025, "week": 7,
"players": ["00-0036389", "DST_SF"],
"slots": { "slots": [{ "slot": "FLEX", "eligible": ["RB","WR","TE"] }], "bench": 4 } }'read a board pro
every row carries points above average starter, which is the only honest way to compare a tight end to a linebacker: a player's ppg minus the startable level at their own position.
curl "https://sicko-fantasy.com/api/v1/analysis/rankings?system=db-team-defense&season=2025&pos=DB&sort=paa" \ -H "Authorization: Bearer $SICKO_KEY"
Notes worth knowing
- ids are entity ids. a player is an nflverse gsis id like
00-0036389; a team defense isDST_SF. both work everywhere a player id is taken. - lineups lock. in a league playing the season being played now, a player whose game has kicked off cannot be moved into or out of a lineup, and cannot be dropped. that is a
409with"error": "locked". - a league imported from sleeper is a mirror. its rosters are re-read every night, so adds, claims and trades are refused in it. make the move on sleeper and sync.
- scores are hindsight, not projection. the optimizer values players by what they actually scored that week under your rules. hand the same solver projections and nothing about the answer changes.