Skip to main content

Sleeper

Sleeper supplies the player master, injury statuses and weekly projections. It needs no account or API key. Its player ID is the system's primary key for players.

What does it provide?​

DataEndpointWritten toUsed for
Player master: name, position, team, status, injury statusapi.sleeper.app/v1/players/nflplayersEligibility, the injury filter, alerts
Weekly projected points for QB, RB, WR and TEapi.sleeper.com/projections/nfl/{season}/{week}weekly_stats.projected_pointsVORP and the optimizers
  • Positions kept: QB, RB, WR, TE, K and DEF. Sleeper's DEF is stored as D/ST.
  • Scoring assumption: projections read the full-PPR point field. Other formats need a code change.
  • Gaps: Sleeper has no kicker or D/ST projections. Those come from ESPN.

How do injury changes flow?​

sync_players compares each fetch with the stored rows and writes only players whose status changed. When a rostered player moves to Questionable, Doubtful or Out, it publishes an INJURY_STATUS_CHANGE message to waiver_actions.

  • The database write and the publish share one transaction. If the publish fails, the write rolls back and the next run sees the change again.
  • The lineup optimizer excludes Out players. Questionable and Doubtful players stay eligible.

How are Sleeper and ESPN IDs matched?​

Sleeper and ESPN IDs overlap numerically but identify different players. A crosswalk maps one to the other.

StepSource
sync_id_crosswalkThe DynastyProcess ID table, loaded through nflreadpy. It sets espn_id and gsis_id for most skill players.
sync_skill_position_crosswalkMatches the remaining QB, RB, WR and TE players to ESPN by name and team.
sync_kicker_dstSets IDs for kickers and D/ST from ESPN.

Every message bound for ESPN carries ESPN IDs. Core rejects a Sleeper ID with a 422. See the architecture and Ingestion for run order.

When does it run?​

JobSchedule (America/Chicago)
fantasy-rapid-status-syncerEvery 10 min on Thursday, Sunday and Monday
fantasy-draft-prep-refresherDaily 18:00, including projections

A Redis lock limits the player sync to one real fetch per 24 hours. Pass --force to override it.

Rate limits and failures​

Sleeper's API is unauthenticated and the client has no rate limiter. The daily gate and the schedule keep request volume low.

FailureResult
Player fetch fails after 3 triesThe sync exits quietly and keeps stored data.
Projections fetch failsThe Job fails and the next run retries.
A position class comes back emptyThe sync raises rather than saving a partial player set.
The run crashes mid-syncThe "in progress" lock expires after 5 minutes.

Where is the code?​

fantasy-core-pipeline: src/ingestion/sync_players.py, sync_projections.py, sync_id_crosswalk.py.