Skip to Content

Low Hold Opportunities

Find markets with the lowest vig (hold) across sportsbooks — the tightest lines available.

GET /api/v1/opportunities/low_hold

The canonical path uses an underscore. /opportunities/low-hold and /opportunities/lowhold respond with a 308 Permanent Redirect to /opportunities/low_hold.

AuthenticationPermalink for this section

Requires API key. Pro tier or higher required. Your account must have the low_hold feature enabled.

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.

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
max_holdnumber5.0Maximum hold percentage (vig). Lower = tighter lines.
livebooleantrue = live only, false = prematch only, omit = both
sortstringholdSort field: hold (lowest first, default), market, sport
limitinteger50Results per page (max 200)
offsetinteger0Pagination offset (max 5000)

Filtering Multiple ValuesPermalink for this section

Use comma-separated values for multi-select filters:

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

Example RequestsPermalink for this section

# Low-hold moneylines under 2% vig curl -X GET "https://api.sharpapi.io/api/v1/opportunities/low_hold?league=nba&max_hold=2&market=moneyline" \ -H "X-API-Key: YOUR_API_KEY" # Prematch only, tightest first curl -X GET "https://api.sharpapi.io/api/v1/opportunities/low_hold?league=mlb&live=false" \ -H "X-API-Key: YOUR_API_KEY"

ResponsePermalink for this section

Success (200)Permalink for this section

Real response for GET /api/v1/opportunities/low_hold?league=mlb&limit=1 (captured 2026-07-02):

{ "data": [ { "all_books": [ "prophetx", "sx_bet" ], "away_team": "Tampa Bay Rays", "confidence": 50, "detected_at": "2026-07-02T18:24:09Z", "event_id": "mlb_rays_royals_2026-07-02_b3", "event_name": "Tampa Bay Rays @ Kansas City Royals", "hold_percentage": 0.22, "home_team": "Kansas City Royals", "id": "714fd29bebedf778", "is_alternate_line": false, "is_live": false, "is_player_prop": false, "league": "mlb", "league_label": "MLB", "line": null, "market_label": "Moneyline", "market_type": "moneyline", "odds_age_seconds": 28.5, "player_name": null, "possibly_stale": false, "side1": { "books": [ "prophetx" ], "external_event_id": "10078595", "fair_probability": 0.4685, "line": null, "market_id": null, "odds_american": 113, "odds_decimal": 2.13, "odds_probability": 0.4695, "selection": "Kansas City Royals", "selection_id": null }, "side2": { "books": [ "sx_bet" ], "external_event_id": "L18646242", "fair_probability": 0.5315, "line": null, "market_id": null, "odds_american": -114, "odds_decimal": 1.877, "odds_probability": 0.5327, "selection": "Tampa Bay Rays", "selection_id": null }, "side3": null, "sport": "baseball", "start_time": "2026-07-02T23:40:00Z", "stat_category": null } ], "pagination": { "count": 1, "has_more": true, "limit": 1, "next_offset": 1, "offset": 0, "total": 66 }, "updated_at": "2026-07-02T18:24:10.961117123Z" }

Response HeadersPermalink for this section

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

Error ResponsesPermalink for this section

401 Unauthorized

No key supplied returns missing_api_key; a bad key returns invalid_api_key.

{ "error": { "code": "missing_api_key", "message": "API key required. Pass via X-API-Key header, api_key query parameter, or Bearer token.", "docs": "https://sharpapi.io/docs/authentication" } }

403 Tier Restricted

{ "error": { "code": "tier_restricted", "message": "This endpoint requires Pro tier or higher", "docs": "https://sharpapi.io/pricing", "tier": "hobby", "required_tier": "pro" } }

429 Rate Limited

retry_after is a Unix-millisecond timestamp of the next window (not a duration); the Retry-After header carries the equivalent seconds value.

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded for pro tier (300/min)", "retry_after": 1737853260000, "tier": "pro", "limit": 300, "docs": "https://sharpapi.io/pricing" } }

Response FieldsPermalink for this section

FieldTypeDescription
idstringUnique low-hold identifier (hash)
event_idstringEvent identifier
event_namestringHuman-readable event name
sportstringSport identifier (lowercase)
leaguestringLeague identifier
market_typestringMarket type (moneyline, point_spread, total_points, etc.)
market_labelstringHuman-readable market name
league_labelstringHuman-readable league name
home_teamstringHome team name
away_teamstringAway team name
start_timestring|nullISO 8601 event start time
linenumber|nullSpread/total line (e.g., -3.5, 220.5)
hold_percentagenumberMarket hold/vig percentage (e.g., 1.8 = 1.8%)
side1objectFirst side of the market
side2objectSecond side of the market
side3object|nullThird side (only for 3-way markets like soccer moneyline)
is_livebooleanWhether the event is currently live
is_alternate_linebooleanWhether this uses a non-standard line
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)
all_booksstring[]All sportsbooks participating in this market
confidencenumberConfidence metric (0-100)
odds_age_secondsnumberAge of the stalest odds in seconds
possibly_stalebooleanWhether odds data may have moved since detection
detected_atstringWhen the opportunity was detected (ISO 8601)

Side ObjectPermalink for this section

FieldTypeDescription
selectionstringThe selection name (e.g., “Lakers”, “Over”)
booksstring[]Sportsbooks offering the best price on this side
linenumber|nullLine value for this side
odds_americannumberAmerican odds
odds_decimalnumberDecimal odds
odds_probabilitynumberImplied probability (0-1)
fair_probabilitynumberFair probability adjusted for hold
selection_idstring|nullSportsbook’s native selection/outcome ID
market_idstring|nullSportsbook’s native market ID
external_event_idstring|nullSportsbook’s native event ID

What Is Hold?Permalink for this section

Hold (also called vig or juice) is the sportsbook’s built-in margin on a market. It’s the difference between the combined implied probabilities and 100%.

Hold % = (implied_prob_side1 + implied_prob_side2 - 1) × 100

ExamplePermalink for this section

DraftKings: Lakers +145 (implied 40.8%) Pinnacle: Celtics -155 (implied 60.8%) Combined: 101.6% Hold: 1.6%

A 1.6% hold means the sportsbook keeps ~$1.60 of every $100 wagered on this market. Lower hold = better value for bettors.

Why Low Hold MattersPermalink for this section

Hold %QualityTypical Source
< 1.5%ExcellentSharp books, cross-book best price
1.5 - 3%GoodCompetitive markets
3 - 5%AverageStandard retail pricing
5%+PoorProps, exotic markets

Low-hold markets give you better odds regardless of which side you bet. Combined with +EV detection, they help maximize expected returns.

Low Hold vs ArbitragePermalink for this section

Low HoldArbitrage
HoldLow but > 0%Below 0% (negative hold)
RiskNormal (you pick a side)Zero (bet both sides)
Use caseGet the best priceGuarantee profit
VolumeHundreds availableRare (single digits)

Low-hold opportunities are far more common than arbitrage. They represent the tightest available lines across books — ideal for bettors who want the best price without needing to bet both sides.

Three-Way MarketsPermalink for this section

For sports with three outcomes (soccer, hockey full-time result), the response includes side3:

{ "side1": { "selection": "Home Win", "..." : "..." }, "side2": { "selection": "Draw", "..." : "..." }, "side3": { "selection": "Away Win", "..." : "..." }, "hold_percentage": 2.1 }

The hold calculation extends to all three sides: implied_prob_1 + implied_prob_2 + implied_prob_3 - 1.

Best PracticesPermalink for this section

  1. Set a tight max_hold — Use max_hold=2 or max_hold=3 to focus on the best-value markets
  2. Resolve bet slips separately — Low-hold rows return prices, not per-side deep links; use the Deep Links endpoint to route users to a book
  3. Combine with +EV data — Low hold + positive EV is the ideal combination
  4. Check possibly_stale — Skip opportunities where odds may have already moved
  5. Use streaming — Subscribe to low_hold:detected events via SSE or WebSocket for real-time alerts
  6. Monitor all_books — More books participating generally means more reliable pricing
Last updated on