Sports arbitrage scanner with Slack alerts
Scan US and European sportsbooks every 15 minutes for guaranteed-profit arbitrage opportunities and get them pushed to Slack with stake splits ready to place.
Build a deterministic sports arbitrage scanner that watches The Odds API for guaranteed-profit opportunities across bookmakers and pushes them into Slack the moment they appear.
Trigger: cron every 15 minutes. Only run inside a configurable active-hours window (default: a wide US window, 9am to 1am US Eastern). Skip the run entirely outside the window.
Inputs (all should be workflow-configurable with sensible defaults):
- Sports list, as The Odds API sport keys. Default: americanfootball_nfl, basketball_nba, baseball_mlb, icehockey_nhl, americanfootball_ncaaf, basketball_ncaab.
- Regions, comma-separated. Default: us,us2,eu.
- Market: h2h (moneyline) only. Odds format: decimal.
- Bankroll size in dollars. Default: 1000.
- Minimum profit margin to alert on. Default: 0.005 (0.5%).
- Slack channel ID (or name) to post alerts to.
On each tick:
1) For each configured sport, call The Odds API "Get Odds" with the configured regions, markets=h2h, oddsFormat=decimal. Be efficient with credits: one call per sport with all regions joined is fine.
2) For each event returned: skip if commence_time is within 10 minutes of now (too late to place both legs). Then for each outcome name across the event (e.g. Team A, Team B, and Draw if present), find the best (highest) decimal price across all returned bookmakers and remember which bookmaker offered it.
3) Compute the arbitrage sum: sum of 1/best_price across all outcomes. If sum < 1.0, this is an arbitrage. Profit margin = 1 - sum. Skip if profit margin is below the configured minimum.
4) Compute the stake split for the configured bankroll: stake_i = bankroll * (1/best_price_i) / sum. Round to two decimals. Guaranteed payout = bankroll / sum.
5) Deduplicate within the run by (event_id, set of bookmakers used) so the same opportunity at the same book pair is not posted twice in one tick.
6) For each surviving arb, use Slack's "Send a Message" operation to post to the configured channel. Format the message clearly:
- Header: sport, matchup (Home vs Away), and commence time in US Eastern.
- Profit line: profit margin as a percentage and the guaranteed payout for the configured bankroll.
- Per-leg lines: outcome name, bookmaker title, decimal price, and stake to place.
- Footer: tick timestamp.
Use Slack mrkdwn formatting (*bold*, not **bold**).
Error handling: if The Odds API returns 429 with OUT_OF_USAGE_CREDITS, log it and exit cleanly (do not post). If a single sport call fails, continue with the others. Log how many credits were consumed using the x-requests-last header so the user can monitor quota drift.
The math is fully deterministic, so this should be implemented as a code workflow (no LLM in the loop).
Additional information
What does this prompt do?
- Every 15 minutes during your active hours, pulls live moneyline odds across major US and European sportsbooks for the sports you care about.
- Finds events where the best available prices across books add up to a guaranteed profit (a real arbitrage), no matter which side wins.
- Posts each opportunity to Slack with the matchup, the two books you'd bet at, the exact stake split for your configured bankroll, and the locked-in profit percentage.
- Skips opportunities that tip off in under 10 minutes and avoids reposting the same arb twice in a run, so the alert feed stays clean and actionable.
What do I need to use this?
- A The Odds API account (the free Starter plan gets you 500 monthly credits to try it out).
- A Slack workspace and the channel you want the alerts to land in.
- Your bankroll size and the list of sports you want to watch (defaults to NFL, NBA, MLB, NHL, NCAAF, and NCAAB).
How can I customize it?
- Change how often it scans, or narrow the active hours to your local evening window.
- Pick which sports, regions, and bookmakers are included so the scanner only watches books you can actually bet at.
- Set your bankroll and minimum profit threshold so only arbs above a certain edge get pushed to Slack.
Frequently asked questions
What is sports arbitrage and is this finding real opportunities?
Will the free Starter plan from The Odds API be enough?
How do I change which Slack channel the alerts go to?
Will it spam me with the same arbitrage over and over?
Why does it skip events that start in under 10 minutes?
Stop refreshing odds screens looking for an edge.
Connect The Odds API and Slack once, and Geni will scan the books every 15 minutes and ping you the second a guaranteed-profit opportunity shows up.