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

AuthenticationPermalink for this section

Requires API key. Pro tier or higher required.

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 (e.g. point_spread, total_points). Supports category aliases — see Odds: Market Category Aliases.
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 200)
offsetinteger0Pagination offset (max 5000)

Example RequestsPermalink for this section

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

ResponsePermalink for this section

Success (200)Permalink for this section

{ "success": true, "data": [ { "id": "a1b2c3d4e5f67890", "event_id": "nfl_bills_chiefs_2026-02-17_b2", "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 HeadersPermalink for this section

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

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": "Middles detection requires Pro tier or higher", "docs": "https://docs.sharpapi.io/en/pricing" } }

Response FieldsPermalink for this section

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 ObjectPermalink for this section

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
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 side’s book: {id, numerical_id, label}.

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

side1 and side2 each gain six optional nested reference objects, mirroring the shape on /odds, /ev, and /arbitrage. The flat top-level fields (sport, league, home_team, away_team, market_type) and per-side book / selection strings are unchanged — the new blocks are purely additive.

{ "side1": { "book": "draftkings", "selection": "Kansas City Chiefs", "line": -2.5, "odds": { "american": -110, "decimal": 1.909, "probability": 0.524, "fair_probability": 0.524 }, "home": { "id": "kansas_city_chiefs", "numerical_id": 11, "name": "Kansas City Chiefs", "abbreviation": "KC", "logo": "https://cdn.opticodds.com/team-logos/football/14.png", "city": "Kansas City", "mascot": "Chiefs", "conference": "AFC", "division": "AFC West" }, "away": { "id": "buffalo_bills", "numerical_id": 4, "name": "Buffalo Bills", "abbreviation": "BUF", "logo": "https://cdn.opticodds.com/team-logos/football/4.png", "city": "Buffalo", "mascot": "Bills", "conference": "AFC", "division": "AFC East" }, "sport_ref": { "id": "football", "numerical_id": 2, "name": "Football" }, "league_ref": { "id": "nfl", "numerical_id": 90, "label": "NFL" }, "market_ref": { "id": "point_spread","numerical_id": 880, "label": "Point Spread" }, "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 both sides of the same middle — the sides differ only in sportsbook_ref, selection, line, and the price. See Entity reference IDs for the full contract.

Warning FlagsPermalink for this section

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 EndpointPermalink for this section

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?Permalink for this section

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 ExamplePermalink for this section

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 NumbersPermalink for this section

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)Permalink for this section

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 GuidePermalink for this section

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 ConsiderationsPermalink for this section

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 FreshnessPermalink for this section

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 PracticesPermalink for this section

  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