Skip to Content
API ReferenceArbitrage

Arbitrage Opportunities

Find guaranteed-profit arbitrage opportunities across sportsbooks.

GET /api/v1/opportunities/arbitrage

AuthenticationPermalink for this section

Requires API key. Hobby tier or higher required. Your account must have the arbitrage feature enabled.

Query ParametersPermalink for this section

ParameterTypeDefaultDescription
sportstringallFilter by sport(s), comma-separated (e.g. basketball, football)
leaguestringallFilter by league(s), comma-separated (e.g. nba, nfl, nhl)
sportsbookstringtier-allowedFilter by sportsbook(s), comma-separated. Tier limits enforced.
marketstringallFilter by market type(s), comma-separated. Supports category aliases — see Odds: Market Category Aliases.
min_profitnumber0.5Minimum profit percentage (e.g. 1.0 = 1%)
livebooleantrue = live only, false = prematch only, omit = both
formatstringjsonResponse format: json or csv. CSV downloads as arbitrage_YYYY-MM-DD.csv.
limitinteger50Results per page (max 200)
offsetinteger0Pagination offset (max 5000)

Profit cap: Opportunities with profit above 10% are automatically filtered out. These are almost always phantom arbs caused by stale or suspended odds rather than real opportunities.

Breaking change: The game_state field (score/period/clock) was removed from this response. Live game state is now served exclusively by the Game State endpoint and the gamestate stream channel. Join rows to game state by event_id.

Filtering Multiple ValuesPermalink for this section

Use comma-separated values for multi-select filters:

?sport=basketball,football&league=nba,nfl

Example RequestsPermalink for this section

curl -X GET "https://api.sharpapi.io/api/v1/opportunities/arbitrage?league=nba&min_profit=1" \ -H "X-API-Key: YOUR_API_KEY"

ResponsePermalink for this section

Success (200)Permalink for this section

{ "success": true, "data": [ { "id": "arb_dk_pin_nba_lal_bos_ml", "event_id": "nba_celtics_lakers_2026-02-08_b3", "event_name": "Los Angeles Lakers @ Boston Celtics", "sport": "basketball", "league": "nba", "market_type": "moneyline", "line": null, "profit_percent": 1.83, "implied_total": 98.2, "is_live": false, "start_time": "2026-02-08T19:00:00Z", "is_alternate_line": false, "possibly_stale": false, "oldest_odds_age_seconds": 8, "warnings": [], "ev_available": true, "ev_percentage": 3.5, "is_player_prop": false, "player_name": null, "stat_category": null, "legs": [ { "sportsbook": "draftkings", "selection": "Los Angeles Lakers", "odds_american": 145, "odds_decimal": 2.45, "implied_probability": 0.408, "stake_percent": 41.5, "timestamp": "2026-02-08T14:22:05.000Z", "external_event_id": "33483153", "selection_id": "sel_lal_ml", "market_id": "mkt_ml_33483153" }, { "sportsbook": "pinnacle", "selection": "Boston Celtics", "odds_american": -135, "odds_decimal": 1.74, "implied_probability": 0.574, "stake_percent": 58.5, "timestamp": "2026-02-08T14:22:08.000Z", "external_event_id": null, "selection_id": null, "market_id": null } ], "detected_at": "2026-02-08T14:22:10.456Z" } ], "pagination": { "limit": 50, "offset": 0, "has_more": false, "next_offset": null }, "meta": { "source": "cache", "summary": { "count": 3, "avg_profit": 1.23, "max_profit": 1.83, "by_market": { "moneyline": 2, "point_spread": 1 }, "by_sport": { "basketball": 3 } }, "filters": { "sport": null, "league": ["nba"], "sportsbook": null, "market": null, "live": null, "min_profit": 1.0 }, "books_analyzed": 8 } }

Response HeadersPermalink for this section

X-RateLimit-Limit: 300 X-RateLimit-Remaining: 297 X-RateLimit-Reset: 1707401000 X-Data-Delay: 0 X-Request-Id: req_arb789xyz012

Error ResponsesPermalink for this section

401 Unauthorized

{ "error": { "code": "unauthorized", "message": "Invalid or missing API key", "docs": "https://docs.sharpapi.io/en/authentication" } }

403 Tier Required

{ "error": { "code": "tier_restricted", "message": "Arbitrage detection requires Hobby tier or higher", "docs": "https://docs.sharpapi.io/en/pricing" } }

429 Rate Limited

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded", "docs": "https://docs.sharpapi.io/en/api-reference/overview" } }

Response FieldsPermalink for this section

FieldTypeDescription
idstringUnique arbitrage identifier (hash)
event_idstringEvent identifier
event_namestringHuman-readable event name
sportstringSport identifier (lowercase)
leaguestringLeague identifier
market_typestringMarket type (moneyline, point_spread, total_points, etc.)
linenumber|nullSpread/total line (e.g., -3.5)
profit_percentnumberGuaranteed profit as a percentage (e.g., 1.83 = 1.83%)
implied_totalnumberSum of implied probabilities across all legs (below 100 = arb exists)
is_livebooleanWhether the event is currently live
start_timestring|nullISO 8601 event start time
is_alternate_linebooleanWhether this uses a non-standard line
possibly_stalebooleanWhether odds may have moved since detection
oldest_odds_age_secondsnumber|nullAge of the stalest leg’s odds in seconds
warningsstring[]Warning flags. Possible values: LIVE_GAME, LIVE_HIGH_PROFIT_SUSPICIOUS, LOW_IMPLIED_TOTAL, POTENTIALLY_STALE_ODDS, VERY_STALE_ODDS
ev_availablebooleanWhether an EV opportunity exists on this market
ev_percentagenumber|nullEV percentage if available
is_player_propbooleanWhether this is a player prop market
player_namestring|nullPlayer name (if player prop)
stat_categorystring|nullStat type (if player prop, e.g., points, rebounds)
legsarrayArray of bet legs that form the arbitrage
detected_atstringISO 8601 timestamp when the arb was first detected

Leg ObjectPermalink for this section

FieldTypeDescription
sportsbookstringSportsbook for this leg
selectionstringThe selection (team name, Over/Under, etc.)
odds_americannumberAmerican odds for this leg
odds_decimalnumberDecimal odds for this leg
implied_probabilitynumberImplied probability (0.0 to 1.0)
stake_percentnumberPercentage of total stake to place on this leg
timestampstring|nullWhen these odds were captured (ISO 8601)
external_event_idstring|nullSportsbook’s native event ID
selection_idstring|nullSportsbook’s selection/outcome ID
market_idstring|nullSportsbook’s market ID
homeobject|undefinedNew (May 2026). Nested home-team reference: {id, numerical_id, name, abbreviation, logo, city, mascot, conference, division}. See Entity reference IDs.
awayobject|undefinedNew (May 2026). Nested away-team reference: {id, numerical_id, name, abbreviation, logo, city, mascot, conference, division}.
sport_refobject|undefinedNew (May 2026). Nested sport reference: {id, numerical_id, name}.
league_refobject|undefinedNew (May 2026). Nested league reference: {id, numerical_id, label}.
market_refobject|undefinedNew (May 2026). Nested market reference: {id, numerical_id, label}.
sportsbook_refobject|undefinedNew (May 2026). Nested sportsbook reference for this leg’s book: {id, numerical_id, label}.

New (May 2026): nested reference blocks on each legPermalink for this section

Every arbitrage leg now carries six optional nested reference objects, mirroring the shape on /odds and /ev. The flat top-level fields (sport, league, home_team, away_team, market_type) and per-leg sportsbook / selection strings are unchanged — the new blocks are purely additive.

{ "legs": [ { "sportsbook": "draftkings", "selection": "Los Angeles Lakers", "odds_american": 145, "home": { "id": "los_angeles_lakers", "numerical_id": 14, "name": "Los Angeles Lakers", "abbreviation": "LAL", "logo": "https://cdn.opticodds.com/team-logos/basketball/13.png", "city": "Los Angeles", "mascot": "Lakers", "conference": "Western", "division": "Pacific Division" }, "away": { "id": "boston_celtics", "numerical_id": 3, "name": "Boston Celtics", "abbreviation": "BOS", "logo": "https://cdn.opticodds.com/team-logos/basketball/2.png", "city": "Boston", "mascot": "Celtics", "conference": "Eastern", "division": "Atlantic Division" }, "sport_ref": { "id": "basketball", "numerical_id": 1, "name": "Basketball" }, "league_ref": { "id": "nba", "numerical_id": 87, "label": "NBA" }, "market_ref": { "id": "moneyline", "numerical_id": 878, "label": "Moneyline" }, "sportsbook_ref": { "id": "draftkings", "numerical_id": 12, "label": "DraftKings" } } ] }

Each block is emitted only when the underlying entity is mapped in the atlas; treat every block (and every inner field) as optional. The two competitor blocks (home, away) are identical across all legs of the same opportunity — the leg differs only in sportsbook_ref, selection, and the price. See Entity reference IDs for the full contract.

CSV FormatPermalink for this section

When ?format=csv, the response downloads as arbitrage_YYYY-MM-DD.csv with columns:

event,sport,market,line,profit%,implied_total,book1,selection1,odds1,stake1%,book2,selection2,odds2,stake2%,is_live,is_alternate_line,possibly_stale,warnings,detected_at

How Arbitrage WorksPermalink for this section

Arbitrage exploits price differences between sportsbooks to guarantee a profit regardless of the outcome. When the combined implied probabilities across all legs of a market total less than 100%, an arbitrage opportunity exists.

The Core PrinciplePermalink for this section

Book A: Team X +150 (implied 40.0%) Book B: Team Y -130 (implied 56.5%) Total implied: 96.5% < 100% = ARBITRAGE

When the total is below 100%, you can bet proportionally on every outcome and guarantee a profit.

Profit CalculationPermalink for this section

Profit % = (100 / implied_total) - 100

Using the example above:

Profit % = (100 / 96.5) - 100 = 3.63%

This means for every $1,000 wagered, you are guaranteed approximately $36.30 in profit.

Calculating Optimal StakesPermalink for this section

To guarantee equal returns regardless of outcome, allocate stakes proportionally:

// Decimal odds: Team X = 2.50, Team Y = 1.77 const impliedX = 1 / 2.50; // 0.400 const impliedY = 1 / 1.77; // 0.565 const total = impliedX + impliedY; // 0.965 const stakeX = impliedX / total; // 41.5% of bankroll const stakeY = impliedY / total; // 58.5% of bankroll

Full Stake ExamplePermalink for this section

Total bankroll for this arb: $1,000

LegStakeOddsPayout if Wins
Team X @ DraftKings$415+150$1,037.50
Team Y @ Pinnacle$585-130$1,035.00

Guaranteed profit: ~$35-38 (3.5-3.8%) regardless of outcome.

Three-Way ArbitragePermalink for this section

Sports like soccer and hockey have three-way markets (home/draw/away), which can also produce arbitrage:

Home Win: +200 (33.3%) Draw: +250 (28.6%) Away Win: +180 (35.7%) Total implied: 97.6% -> 2.4% arbitrage profit

The same stake calculation applies — divide each leg’s implied probability by the total to determine the stake allocation.

Why Arbs ExistPermalink for this section

  1. Timing differences - Sportsbooks update odds at different speeds
  2. Differing opinions - Books have different risk models and exposure
  3. Promotions - Boosted odds from one book create artificial gaps
  4. Errors - Occasionally, a book posts incorrect odds

Best PracticesPermalink for this section

Account Risk: Sportsbooks actively monitor for arbitrage activity. Accounts that exclusively place arb bets may be limited or restricted. Consider mixing arbitrage bets with recreational activity.

  1. Act fast - Arb windows are often short-lived (seconds to minutes)
  2. Round your stakes - A bet of $47.32 looks suspicious; round to $50
  3. Use pre-calculated stakes - The stake_percent field gives you optimal allocation
  4. Verify odds before placing - Always confirm the odds at the sportsbook have not moved
  5. Start with larger arbs - Focus on min_profit=1 or higher to account for line movement
  6. Track the implied_total - Lower totals mean larger guaranteed profits
  7. Diversify sportsbooks - Spreading activity across many books reduces individual account risk

Arb vs +EV BettingPermalink for this section

AspectArbitrage+EV Betting
RiskZero (guaranteed profit)Variance exists
Profit per bet1-3% typical2-10% edge
Account riskHigh (limits likely)Lower
Capital requiredHigh (bet both sides)Lower
SustainabilityLimited by account healthLong-term viable

Many experienced bettors prefer +EV betting over arbitrage because accounts last longer and the expected edges are often larger. See the +EV Opportunities endpoint for details.

Last updated on