Skip to Content

Middles

Find middle opportunities where two sportsbooks have different lines, creating a gap where both bets can win.

GET /api/v1/opportunities/middles

Authentication

Requires API key. Pro tier or higher required.

Query Parameters

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 (e.g. point_spread, total_points)
min_sizenumber0.5Minimum middle size in points
livebooleantrue = live only, false = prematch only, omit = both
max_odds_agenumberMax odds age in seconds. Filters out stale opportunities.
sortstringqualitySort field: quality (default), ev, probability, middle_size
limitinteger50Results per page (max 500)
offsetinteger0Pagination offset (max 5000)

Example Requests

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

Response

Success (200)

{ "success": true, "data": [ { "id": "a1b2c3d4e5f67890", "event_id": "evt_nfl_buf_kc_20260217", "event_name": "Buffalo Bills @ Kansas City Chiefs", "sport": "football", "league": "nfl", "market_type": "point_spread", "home_team": "Kansas City Chiefs", "away_team": "Buffalo Bills", "start_time": "2026-02-17T20:00:00Z", "side1": { "book": "draftkings", "selection": "Kansas City Chiefs", "line": -2.5, "odds": { "american": -110, "decimal": 1.909, "probability": 0.524, "fair_probability": 0.524 }, "stake_percent": 50.12, "odds_age_seconds": 5.0 }, "side2": { "book": "fanduel", "selection": "Buffalo Bills", "line": 7.5, "odds": { "american": -108, "decimal": 1.926, "probability": 0.519, "fair_probability": 0.519 }, "stake_percent": 49.88, "odds_age_seconds": 12.3 }, "middle_size": 5.0, "middle_numbers": [3, 4, 5, 6, 7], "middle_probability": 0.377, "expected_value": 31.52, "roi_percentage": 31.52, "worst_case_loss": -4.13, "best_case_profit": 83.54, "break_even_percent": 4.71, "odds_age_seconds": 12.3, "is_guaranteed_profit": false, "guaranteed_roi": null, "key_numbers": [3, 7], "key_number_probability": 0.242, "is_live": false, "is_player_prop": false, "player_name": null, "stat_category": null, "warnings": ["HIGH_PROBABILITY", "LARGE_GAP"], "detected_at": "2026-02-17T19:45:30Z" } ], "meta": { "count": 1, "total": 47, "source": "cache", "pagination": { "limit": 50, "offset": 0, "has_more": false, "next_offset": null }, "summary": { "count": 47 }, "filters": { "sport": null, "league": ["nfl"], "sportsbook": null, "market": null, "min_size": 1 }, "updated_at": "2026-02-17T19:45:30Z" } }

Response Headers

X-RateLimit-Limit: 300 X-RateLimit-Remaining: 296 X-RateLimit-Reset: 1707401000 X-Data-Delay: 0 X-Request-Id: req_mid456abc789

Error Responses

401 Unauthorized

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

403 Tier Required

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

Response Fields

FieldTypeDescription
idstringUnique middle identifier (hash)
event_idstringEvent identifier
event_namestringHuman-readable event name
sportstringSport identifier
leaguestringLeague identifier
market_typestringMarket type (point_spread, total_points, player prop types)
home_teamstringHome team name
away_teamstringAway team name
start_timestring|nullGame start time (ISO 8601)
side1objectFirst side of the middle bet
side2objectSecond side of the middle bet
middle_sizenumberSize of the middle gap in points
middle_numbersnumber[]Integer values that would hit the middle
middle_probabilitynumberEstimated probability of middle hitting (sport-specific)
expected_valuenumberEV in dollars per $100 total wagered
roi_percentagenumberEV as percentage of total stake
worst_case_lossnumberLoss when middle misses (negative = loss)
best_case_profitnumberProfit when middle hits (both bets win)
break_even_percentnumberMinimum hit rate needed to break even
odds_age_secondsnumber|nullAge of stalest underlying odds at detection time
is_guaranteed_profitbooleanTrue when worst_case_loss >= 0 (arb + middle)
guaranteed_roinumber|nullWorst-case ROI% when guaranteed (null otherwise)
key_numbersnumber[]Key numbers in middle range (e.g., NFL 3, 7)
key_number_probabilitynumberCombined probability of key numbers only
quality_scorenumberMulti-factor quality metric (0-100)
market_overroundnumberCombined implied probability across both sides
is_livebooleanWhether the game is currently in-play
is_player_propbooleanWhether this is a player prop middle
player_namestring|nullPlayer name (if player prop)
stat_categorystring|nullStat type (if player prop, e.g., points, rebounds)
warningsstring[]Warning flags (see below)
detected_atstringWhen the middle was detected (ISO 8601)

Side Object

FieldTypeDescription
bookstringSportsbook for this side
selectionstringThe selection name
linenumberThe line value at this sportsbook
odds.americannumberAmerican odds
odds.decimalnumberDecimal odds
odds.probabilitynumberImplied probability (0-1)
odds.fair_probabilitynumberFair probability adjusted for overround
stake_percentnumberRecommended stake allocation (% of total)
odds_age_secondsnumber|nullAge of this side’s odds at detection time
deep_linkstring|nullDirect link to place this bet at the sportsbook

Warning Flags

WarningMeaning
HIGH_PROBABILITYMiddle probability exceeds 15% — unusually likely to hit
LARGE_GAPMiddle size exceeds 3 points — verify lines are correct
STALE_ODDSOne or both odds are older than 30 seconds
LIVE_GAMEGame is currently in progress
GUARANTEED_PROFITWorst-case loss is positive — this is also an arbitrage

Detail Endpoint

Fetch a single middle opportunity by its ID.

GET /api/v1/opportunities/middles/:id
ParameterTypeDescription
idpathRequired. 16-character hex hash (e.g., a1b2c3d4e5f67890)

Returns a single middle object (same schema as the list items). Returns 404 if not found, 400 if the ID format is invalid.

curl -X GET "https://api.sharpapi.io/api/v1/opportunities/middles/a1b2c3d4e5f67890" \ -H "X-API-Key: YOUR_API_KEY"

What Are Middles?

A middle occurs when two sportsbooks offer different lines on the same market, creating a numerical gap where both bets can win simultaneously.

Unlike arbitrage (which guarantees profit), middles give you a chance to win both sides of a bet if the final result lands in the “middle” of the two lines.

Spread Middle Example

DraftKings: Chiefs -2.5 @ -110 FanDuel: Bills +7.5 @ -108

You bet:

  • Chiefs -2.5 at DraftKings
  • Bills +7.5 at FanDuel

Possible outcomes:

Chiefs Win ByChiefs -2.5Bills +7.5Result
1-2 pointsLoseWinSplit (small loss)
3, 4, 5, 6, or 7WinWinMIDDLE HIT
8+ pointsWinLoseSplit (small loss)

If the Chiefs win by 3-7, both bets win. The numbers 3 and 7 are NFL key numbers (field goal and touchdown), making this middle especially valuable.

Key Numbers

Certain sports have scoring increments that spike the probability distribution:

SportKey NumbersWhy
NFL3, 7, 10, 14Field goal (3), touchdown (7), combinations
NHL1Most games decided by 1 goal (~47%)
MLB1Most games decided by 1 run (~30%)
Soccer1Most matches decided by 1 goal (~38%)

When a middle contains key numbers, the key_numbers and key_number_probability fields highlight this. An NFL middle spanning 3 and 7 has a combined key number probability of ~24.2%.

Guaranteed Profit (Arb + Middle)

When is_guaranteed_profit is true, the middle is also an arbitrage — the worst case still yields a profit. This is the rarest and most valuable type of middle. The guaranteed_roi field shows the minimum return even if the middle misses.

Middle Size Guide

Middle SizeQualityTypical Markets
0.5 pointsNarrowRare opportunities, low hit rate
1.0 pointsStandardCommon in spreads and totals
1.5 - 2.0 pointsGoodLook for these actively
2.5+ pointsExcellentUncommon but highly profitable

Use min_size=1 to filter out narrow middles. Larger middles have a higher probability of landing in the gap, making them more consistently profitable over time.

Risk Considerations

Middles are not risk-free like arbitrage (unless is_guaranteed_profit is true). When the result falls outside the middle, you lose the vig on the losing side (typically 4-5% of one leg). However, when a middle hits, you win both bets, which more than compensates over time.

Odds Freshness

The odds_age_seconds field shows how old the underlying odds were when the middle was detected. Each side also has its own odds_age_seconds. If either side exceeds 30 seconds, the STALE_ODDS warning is added. Stale odds may have already moved — act quickly on fresh opportunities.

Best Practices

  1. Focus on larger middles — Set min_size to at least 1.0 for better hit rates
  2. Watch for key numbers — Middles containing NFL 3/7 or NHL/MLB/soccer 1 have elevated hit rates
  3. Prioritize guaranteed profit — Filter for is_guaranteed_profit to find risk-free opportunities
  4. Check odds freshness — Low odds_age_seconds means the lines are current and actionable
  5. Combine with the summary endpoint — Use /middles/summary for dashboard overviews
  6. Act quickly — Lines converge as books adjust, closing the middle window
  7. Use streaming — Subscribe to middles:detected events via SSE or WebSocket for real-time alerts
Last updated on