FILTERS
Props
0
Betr Best
0
Obs saved
0
๐
Set filters, then click Fetch Lines
Hit Fetch Lines to load Betr standard props ranked by PP value
Hit Run Scan to find edges and build a slip
Distribution Curves
Enter a standard line to see the market prior curve. Add a player to overlay their historical distribution.
Season
Market
Player
Games
Standard line
Enter a standard line to view curveoptionally add a player to overlay historical data
Loading...
Payout Reference
Break-even probability is the per-leg win rate needed for EV = 0. Flex Play accounts for all partial payout tiers in the calculation.
Loadingโฆ
API Reference
Railway: betr-picks-production.up.railway.app
| Method | Endpoint | Triggered by | Description | ntfy? |
|---|---|---|---|---|
| GET | /health | โ | Ping โ returns {status: "ok"} | โ |
| POST | /refresh-token | token-refresh service (8 min) / Vercel "Refresh Token" btn | Accepts fresh JWT, updates in-memory cache + PP_JWT_CACHE env var, clears backoff. Body: {token, exp} | โ |
| GET | /token-status | โ | JWT validity and seconds until expiry | โ |
| GET | /screener-status | โ | Last screener run time, edge count, alert status, backoff remaining | โ |
| GET | /screener-edges | Screener tab | Edges from the most recent screener run. Reads Supabase edges table (falls back to in-memory) so it survives restarts. | โ |
| POST | /screen | Direct call only | Manually trigger a full screener scan across all SCAN_MARKETS. Returns edges found, sends ntfy push if any. | โ |
| GET | /betr-active-leagues | Direct call only | Every league live/upcoming on Betr right now + whether we have a PP market mapping for it yet. Cached 10 min. | โ |
| POST | /fetch-lines | Lines tab "Fetch Lines" | Fetches one market+league from PP Screen. Saves prop_observations to Supabase. Body: {market, league, books, is_live, season} | โ |
| GET | /payout-reference | Payout tab | Payout reference table (perfect play + flex, all pick counts) | โ |
| GET | /market-cv-curves | Mkt Curves tab (hidden from nav) | Hardcoded vs. calibrated CV buckets + power-law fit per market, for the curve explorer chart. Feeds off market_cv_calibrated/curve_fits (NBA-driven, empty off-season). | โ |
| GET | /slip-builder | Slip Builder "Run Scan" | Full screener scan + fantasy fetch grouped by game with same-game complements. No alert sent. | โ |
| GET | /ref-detail | Fantasy tab (row expand) | Reference-book odds for one player/market/line. Params: player, market, league, line | โ |
| GET | /fantasy-lines | Fantasy tab "Fetch Lines" | All Betr standard props from PP fantasy optimizer, sorted by value% desc | โ |
| GET | /discover-markets | Direct call only | Batch-probes candidate market names across leagues. Returns hits (has Betr Alt) and misses. Add ?league=Soccer to scope to one league. Slow (~2-5 min full run). | โ |
| GET | /debug-grid | Direct call only | Raw alt-line grid + curve fit for one player/market, across CURVE_BOOKS + DK/FD/Pinnacle. Used to validate curve math. Params: player, market, league | โ |
Background Processes
โ
Screener loop
Runs every 6โ10 min (random jitter) during 8amโ10pm PT. Scans NBA, NCAAB, NHL, Soccer, MLB, WNBA, Tennis. Sends ntfy push on any edges found. 90s startup delay to absorb rapid Railway redeploys. Escalating backoff on PP rate limit (3m โ 10m โ 30m).
External Dependencies
| Service | Purpose | Notes |
|---|---|---|
| Prop Professor | Prop line data + devig | JWT (10 min TTL) via session cookie. Session cookie itself expires ~30 days โ rotate PP_SESSION_TOKEN before then. Rotates on new browser login โ urgent ntfy fires โ tap Refresh Token on Vercel. |
| Betr GraphQL (api.fantasy.betr.app) | Real boost tiers, straight from Betr | Unauthenticated, anonymous โ public prop board data only, never Betr's logged-in surface. src/betr_client.py. Covers MLB, WNBA, Tennis, NFL, Soccer(MLS), UFC via LEAGUE_MAP. Falls back to odds-shape estimate when unmapped. |
| Supabase | Postgres โ prop_observations, edges, curve_fits | Lines tab writes prop_observations. Screener logs edges + curve_fits. market_cv_calibrated/curve_fits are NBA-driven and empty off-season. |
| ntfy.sh | Push alerts to iOS | Topic: betrounds. urgent = session expired. high = rate limited or 3+ edges. default = <3 edges. |
| Railway | FastAPI host (amiable-nature) + token-refresh service | PP_SESSION_TOKEN, PP_JWT_CACHE, SUPABASE_URL, SUPABASE_SERVICE_KEY, NTFY_TOPIC. token-refresh runs on a separate Railway service with a fresh IP pool, pushes JWT every 8 min via /refresh-token. |
| Vercel | Next.js frontend (sports.roundscapital.co) | Auto-deploys from GitHub main. NEXT_PUBLIC_API_URL must point to Railway URL. |