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

Authentication

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 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
max_holdnumber5.0Maximum hold percentage (vig). Lower = tighter lines.
livebooleantrue = live only, false = prematch only, omit = both
statestringpaUS state code for deep link generation (e.g. pa, nj, co, mi)
sortstringholdSort field: hold (lowest first, default), market, sport
limitinteger50Results per page (max 200)
offsetinteger0Pagination offset (max 5000)

Filtering Multiple Values

Use comma-separated values for multi-select filters:

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

Example Requests

# 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" # With state for deep links curl -X GET "https://api.sharpapi.io/api/v1/opportunities/low_hold?league=nfl&state=nj" \ -H "X-API-Key: YOUR_API_KEY"

Response

Success (200)

{ "success": true, "data": [ { "id": "lh_nba_lal_bos_ml_0", "event_id": "evt_nba_lal_bos_20260208", "event_name": "Los Angeles Lakers @ Boston Celtics", "sport": "basketball", "league": "nba", "market_type": "moneyline", "home_team": "Boston Celtics", "away_team": "Los Angeles Lakers", "start_time": "2026-02-08T19:00:00Z", "line": null, "hold_percentage": 1.8, "side1": { "selection": "Los Angeles Lakers", "books": ["draftkings", "betmgm"], "line": null, "odds": { "american": 145, "decimal": 2.45, "implied_probability": 0.408, "fair_probability": 0.415 }, "deep_links": { "draftkings": "https://sportsbook.draftkings.com/...", "betmgm": "https://sports.betmgm.com/..." } }, "side2": { "selection": "Boston Celtics", "books": ["pinnacle", "fanduel"], "line": null, "odds": { "american": -155, "decimal": 1.645, "implied_probability": 0.608, "fair_probability": 0.585 }, "deep_links": { "pinnacle": null, "fanduel": "https://sportsbook.fanduel.com/..." } }, "side3": null, "is_live": false, "is_alternate_line": false, "is_player_prop": false, "player_name": null, "stat_category": null, "all_books": ["draftkings", "betmgm", "pinnacle", "fanduel"], "confidence": 92, "odds_age_seconds": 5, "possibly_stale": false, "detected_at": "2026-02-08T14:22:10.456Z" } ], "pagination": { "limit": 50, "offset": 0, "total": 87, "has_more": true, "next_offset": 50 }, "meta": { "source": "cache", "summary": { "count": 87, "avg_hold": 2.4, "min_hold": 0.8, "by_market": { "moneyline": 35, "point_spread": 30, "total_points": 22 }, "by_sport": { "basketball": 87 } }, "filters": { "sport": null, "league": ["nba"], "sportsbook": null, "market": null, "max_hold": 5.0, "live": null, "state": "pa" } } }

Response Headers

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

Error Responses

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": "This endpoint requires Pro 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 Fields

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.)
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 Object

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.implied_probabilitynumberImplied probability (0-1)
odds.fair_probabilitynumberFair probability adjusted for hold
deep_linksobjectMap of sportsbook name to deep link URL (or null if unavailable)

Deep links are generated based on the state query parameter. Pass your user’s US state code (e.g., ?state=nj) to get correct sportsbook URLs for their jurisdiction.


What Is Hold?

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

Example

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 Matters

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 Arbitrage

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 Markets

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 Practices

  1. Set a tight max_hold — Use max_hold=2 or max_hold=3 to focus on the best-value markets
  2. Pass the state parameter — Get accurate deep links for your user’s jurisdiction
  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