{"openapi":"3.1.0","info":{"title":"Diamond Projections API","version":"1.0.0","description":"Customizable MLB DFS projections, player pools, optimal lineup construction, and player explainers."},"servers":[{"url":"https://diamonddfs.com/api/v1"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Diamond Projections API key (dp_live_...) or a Supabase JWT."}},"schemas":{"ProjectionWeights":{"type":"object","properties":{"vsSP":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the batter-vs-starting-pitcher matchup. INCLUDES batter/pitcher handedness (platoon) splits — there is no separate platoon weight."},"recentTrend":{"type":"number","minimum":0,"maximum":100,"description":"Weight for recent (L14) form: OPS + DK points-per-game trend."},"parkFactor":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the home ballpark's run-scoring environment."},"weather":{"type":"number","minimum":0,"maximum":100,"description":"Weight for game-day weather (temperature, wind, precipitation)."},"teamTotal":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the team's Vegas-implied run total."},"environmentalSplits":{"type":"number","minimum":0,"maximum":100,"description":"Weight for environmental splits: Home/Away, Day/Night, and Grass/Turf OPS deviations. Does NOT include batter/pitcher handedness — that lives in vsSP."}},"required":["vsSP","recentTrend","parkFactor","weather","teamTotal","environmentalSplits"],"additionalProperties":false},"SlateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date (YYYY-MM-DD) of the slate. AMBIGUOUS on multi-slate days — a single date can host Main, Showdown, Afternoon, etc. Prefer `slateId` whenever possible. If passed alone on a date with multiple slates, the API returns 409 `ambiguous_slate` with the candidate slateIds."},"SlateId":{"type":"integer","description":"PREFERRED slate identifier — DraftKings draft group id (dk_draft_group_id) from GET /slates. Canonical and unambiguous: locks the optimizer to exactly one DraftKings contest (Main / Showdown / Afternoon / etc.). DraftKings draft group IDs are typically NEGATIVE integers (e.g. -85369979) — pass the value from GET /slates exactly as returned, including the sign. Always call GET /slates first and pass the returned `slateId` instead of `slateDate`."},"OptimizeInput":{"type":"object","properties":{"slateId":{"type":"integer","description":"PREFERRED. DraftKings draft group id from GET /slates. Locks the optimizer to a specific slate (Main / Showdown / etc.). Use this instead of `slateDate`."},"slateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Fallback only. ISO date (YYYY-MM-DD). Rejected with 409 `ambiguous_slate` on multi-slate days — prefer `slateId`."},"weights":{"type":"object","properties":{"vsSP":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the batter-vs-starting-pitcher matchup. INCLUDES batter/pitcher handedness (platoon) splits — there is no separate platoon weight."},"recentTrend":{"type":"number","minimum":0,"maximum":100,"description":"Weight for recent (L14) form: OPS + DK points-per-game trend."},"parkFactor":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the home ballpark's run-scoring environment."},"weather":{"type":"number","minimum":0,"maximum":100,"description":"Weight for game-day weather (temperature, wind, precipitation)."},"teamTotal":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the team's Vegas-implied run total."},"environmentalSplits":{"type":"number","minimum":0,"maximum":100,"description":"Weight for environmental splits: Home/Away, Day/Night, and Grass/Turf OPS deviations. Does NOT include batter/pitcher handedness — that lives in vsSP."}},"required":["vsSP","recentTrend","parkFactor","weather","teamTotal","environmentalSplits"],"additionalProperties":false},"presetName":{"type":"string","minLength":1,"maxLength":80},"locks":{"type":"array","items":{"type":"string"},"maxItems":10},"excludes":{"type":"array","items":{"type":"string"},"maxItems":50},"salaryCap":{"type":"integer","minimum":20000,"maximum":60000}},"additionalProperties":false},"SlatePlayersInput":{"type":"object","properties":{"slateId":{"type":"integer","description":"PREFERRED. DraftKings draft group id from GET /slates."},"slateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date (YYYY-MM-DD) of the slate. AMBIGUOUS on multi-slate days — a single date can host Main, Showdown, Afternoon, etc. Prefer `slateId` whenever possible. If passed alone on a date with multiple slates, the API returns 409 `ambiguous_slate` with the candidate slateIds."},"weights":{"type":"object","properties":{"vsSP":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the batter-vs-starting-pitcher matchup. INCLUDES batter/pitcher handedness (platoon) splits — there is no separate platoon weight."},"recentTrend":{"type":"number","minimum":0,"maximum":100,"description":"Weight for recent (L14) form: OPS + DK points-per-game trend."},"parkFactor":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the home ballpark's run-scoring environment."},"weather":{"type":"number","minimum":0,"maximum":100,"description":"Weight for game-day weather (temperature, wind, precipitation)."},"teamTotal":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the team's Vegas-implied run total."},"environmentalSplits":{"type":"number","minimum":0,"maximum":100,"description":"Weight for environmental splits: Home/Away, Day/Night, and Grass/Turf OPS deviations. Does NOT include batter/pitcher handedness — that lives in vsSP."}},"required":["vsSP","recentTrend","parkFactor","weather","teamTotal","environmentalSplits"],"additionalProperties":false},"position":{"type":"string","minLength":1,"maxLength":8}},"additionalProperties":false},"LineupSwapInput":{"type":"object","properties":{"slateId":{"type":"integer","description":"PREFERRED. DraftKings draft group id from GET /slates. Locks the swap to a specific slate. Use this instead of `slateDate`."},"slateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Fallback only. Rejected with 409 `ambiguous_slate` on multi-slate days."},"weights":{"type":"object","properties":{"vsSP":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the batter-vs-starting-pitcher matchup. INCLUDES batter/pitcher handedness (platoon) splits — there is no separate platoon weight."},"recentTrend":{"type":"number","minimum":0,"maximum":100,"description":"Weight for recent (L14) form: OPS + DK points-per-game trend."},"parkFactor":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the home ballpark's run-scoring environment."},"weather":{"type":"number","minimum":0,"maximum":100,"description":"Weight for game-day weather (temperature, wind, precipitation)."},"teamTotal":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the team's Vegas-implied run total."},"environmentalSplits":{"type":"number","minimum":0,"maximum":100,"description":"Weight for environmental splits: Home/Away, Day/Night, and Grass/Turf OPS deviations. Does NOT include batter/pitcher handedness — that lives in vsSP."}},"required":["vsSP","recentTrend","parkFactor","weather","teamTotal","environmentalSplits"],"additionalProperties":false},"presetName":{"type":"string","minLength":1,"maxLength":80},"currentLineup":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"minItems":1,"maxItems":10},"playerOut":{"type":"string","minLength":1,"maxLength":80},"excludes":{"type":"array","items":{"type":"string"},"maxItems":50},"salaryCap":{"type":"integer","minimum":20000,"maximum":60000}},"required":["currentLineup","playerOut"],"additionalProperties":false},"PlayerExplainInput":{"type":"object","properties":{"slateId":{"type":"integer","description":"PREFERRED. DraftKings draft group id from GET /slates."},"slateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date (YYYY-MM-DD) of the slate. AMBIGUOUS on multi-slate days — a single date can host Main, Showdown, Afternoon, etc. Prefer `slateId` whenever possible. If passed alone on a date with multiple slates, the API returns 409 `ambiguous_slate` with the candidate slateIds."},"weights":{"type":"object","properties":{"vsSP":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the batter-vs-starting-pitcher matchup. INCLUDES batter/pitcher handedness (platoon) splits — there is no separate platoon weight."},"recentTrend":{"type":"number","minimum":0,"maximum":100,"description":"Weight for recent (L14) form: OPS + DK points-per-game trend."},"parkFactor":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the home ballpark's run-scoring environment."},"weather":{"type":"number","minimum":0,"maximum":100,"description":"Weight for game-day weather (temperature, wind, precipitation)."},"teamTotal":{"type":"number","minimum":0,"maximum":100,"description":"Weight for the team's Vegas-implied run total."},"environmentalSplits":{"type":"number","minimum":0,"maximum":100,"description":"Weight for environmental splits: Home/Away, Day/Night, and Grass/Turf OPS deviations. Does NOT include batter/pitcher handedness — that lives in vsSP."}},"required":["vsSP","recentTrend","parkFactor","weather","teamTotal","environmentalSplits"],"additionalProperties":false}},"additionalProperties":false}}},"security":[{"bearerAuth":[]}],"paths":{"/health":{"get":{"summary":"Service health","security":[],"responses":{"200":{"description":"ok"}}}},"/slates":{"get":{"summary":"List available DraftKings slates (with slateId)","description":"Returns the canonical per-slate list. Each item has `slateId` (dk_draft_group_id), `slateDate`, `contestType`, `contestLabel`, `gameCount`, `startTimeUtc`, and `playerCount`. A single date can appear with multiple slateIds (Main, Showdown, etc.).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":120}}],"responses":{"200":{"description":"Recent slates (with `latest` + legacy `dates`)"}}}},"/slates/{date}/players":{"get":{"summary":"Player pool for a slate date (ambiguous on multi-slate days)","description":"Returns the projected player pool for `date`. If the date has multiple DraftKings slates, responds with 409 `ambiguous_slate` and the candidate slateIds. Prefer `/slates/by-id/{slateId}/players`.","parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"weights","in":"query","description":"JSON-encoded ProjectionWeights","schema":{"type":"string"}},{"name":"position","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Projected players"},"409":{"description":"Ambiguous slate — multiple slates exist for this date"}}}},"/slates/by-id/{slateId}/players":{"get":{"summary":"Player pool for a specific DraftKings slate (canonical)","description":"Returns the projected player pool for the exact DraftKings slate identified by `slateId` (dk_draft_group_id). Use the slateId from GET /slates.","parameters":[{"name":"slateId","in":"path","required":true,"schema":{"type":"integer","minimum":1}},{"name":"weights","in":"query","description":"JSON-encoded ProjectionWeights","schema":{"type":"string"}},{"name":"position","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Projected players"}}}},"/optimize":{"post":{"summary":"Build optimal DFS lineup","description":"Pass `slateId` to lock the DraftKings slate. `slateDate` alone is ambiguous on multi-slate days.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OptimizeInput"}}}},"responses":{"200":{"description":"Optimal lineup"}}}},"/lineup/swap":{"post":{"summary":"Swap a player out of a lineup and re-optimize","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineupSwapInput"}}}},"responses":{"200":{"description":"Updated lineup"}}}},"/players/{id}/projection":{"get":{"summary":"Detailed projection breakdown for a player","parameters":[{"name":"id","in":"path","required":true,"description":"DraftKings player id, internal id, or full name","schema":{"type":"string"}},{"name":"slateId","in":"query","description":"Preferred — DraftKings draft group id from /slates","schema":{"type":"integer","minimum":1}},{"name":"slateDate","in":"query","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"weights","in":"query","description":"JSON-encoded ProjectionWeights","schema":{"type":"string"}}],"responses":{"200":{"description":"Player breakdown"}}}},"/weights/presets":{"get":{"summary":"List saved weight presets","responses":{"200":{"description":"Presets"}}}},"/opponent-wrc":{"get":{"summary":"Team wRC+ (last 30 days) with ranks","responses":{"200":{"description":"Team wRC+ map + ranks"}}}}}}