Skip to Content
API Reference+EV Opportunities

+EV Opportunities

Find positive expected value betting opportunities across all sportsbooks.

GET /api/v1/opportunities/ev

This endpoint replaces the former /positive-ev and /value-bets endpoints. All scoring fields (confidence_score, kelly_fraction, fair_probability) are now included in every response.

Authentication

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

Query Parameters

ParameterTypeDefaultDescription
sportstringallFilter by sport(s), comma-separated (e.g. basketball, football, ice_hockey)
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 categories (spread, total, moneyline, props) or exact types (point_spread, player_points).
eventstringallFilter by game/event ID(s), comma-separated
min_evnumber0Minimum EV percentage threshold
max_evnumberMaximum EV percentage threshold
livebooleantrue = live only, false = prematch only, omit = both
min_oddsnumberMinimum American odds (e.g., -200)
max_oddsnumberMaximum American odds (e.g., +500)
min_market_widthnumberMinimum market width (vig indicator). Lower width = sharper market.
max_market_widthnumberMaximum market width
max_odds_agenumberMaximum odds age in seconds. Filters out stale opportunities where the underlying odds are older than this threshold.
date_rangestringFilter by event date: today, tomorrow, or week. Dates are evaluated in US Eastern Time (ET).
sortstring-evSort field. Options: ev, confidence/confidence_score, kelly/kelly_fraction, time/start_time, book_count/books. Prefix with - for descending.
limitinteger50Results per page (max 500)
offsetinteger0Pagination offset (max 5000)

Filtering Multiple Values

Use comma-separated values for multi-select filters:

?sportsbook=draftkings,fanduel&league=nba,nfl

Example Requests

# Basic EV opportunities for NBA curl -X GET "https://api.sharpapi.io/api/v1/opportunities/ev?league=nba&min_ev=2" \ -H "X-API-Key: YOUR_API_KEY"

Response

Success (200)

{ "success": true, "data": [ { "id": "ev_dk_nba_33483153_ml_PHO", "game_id": "evt_nba_phi_pho_20260208", "ev_percent": 4.2, "odds_american": -105, "odds_decimal": 1.952, "no_vig_odds": -118, "fair_probability": 0.541, "market_width": 3.2, "devig_method": "power", "devig_book": "pinnacle", "selection": "PHO Suns", "market": "moneyline", "line": null, "sportsbook": "draftkings", "game": "PHI 76ers vs PHO Suns", "sport": "basketball", "league": "nba", "home_team": "PHI 76ers", "away_team": "PHO Suns", "start_time": "2026-02-08T19:00:00Z", "is_live": false, "confidence_score": 87, "kelly_fraction": 0.021, "book_count": 5, "arb_available": false, "arb_profit": null, "is_player_prop": false, "player_name": null, "stat_category": null, "possibly_stale": false, "oldest_odds_age_seconds": null, "warnings": [], "detected_at": "2026-02-08T14:22:10.456Z" } ], "pagination": { "limit": 50, "offset": 0, "total": 12, "maxOffset": 5000 }, "meta": { "source": "redis", "last_update": "2026-02-08T14:22:10.456Z", "summary": { "count": 12, "avg_ev": 3.8, "max_ev": 7.1, "by_sportsbook": { "draftkings": 5, "fanduel": 4, "betmgm": 3 }, "by_sport": { "basketball": 12 }, "by_market": { "moneyline": 5, "point_spread": 4, "player_points": 3 } }, "filters": { "sport": null, "league": ["nba"], "sportsbook": null, "market": null, "min_ev": 2.0, "max_ev": null, "live": null, "sort": "-ev", "include": null } } }

Response Headers

X-RateLimit-Limit: 300 X-RateLimit-Remaining: 298 X-RateLimit-Reset: 1707401000 X-Data-Delay: 0 X-Request-Id: req_abc123def456

Error Responses

401 Unauthorized

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

403 Feature Required

{ "error": { "code": "feature_required", "message": "The 'ev' feature is required. Upgrade to Pro or higher.", "docs": "https://sharpapi.io/docs/pricing" } }

429 Rate Limited

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

Response Fields

Core Fields

FieldTypeDescription
idstringUnique opportunity identifier (hash)
game_idstring|nullAssociated game/event identifier
external_event_idstring|nullSportsbook’s native event ID
selection_idstring|nullSportsbook’s native outcome/selection ID (for deep linking to the bet slip)
ev_percentnumberExpected value as a percentage (e.g., 4.2 = 4.2% EV)
odds_americannumberCurrent American odds at the sportsbook
odds_decimalnumberDecimal odds (e.g., 1.952)
no_vig_oddsnumber|nullFair (no-vig) American odds derived from the sharp line
fair_probabilitynumber|nullNo-vig (devigged) fair probability (0.0 to 1.0)
market_widthnumber|nullWidth of the market (vig indicator)
devig_methodstringDe-vig method used (e.g., power)
devig_bookstringSharp book used as reference (e.g., pinnacle)
selectionstringThe selection (team name, Over/Under, player, etc.)
marketstringMarket type (moneyline, point_spread, total_points, etc.)
linenumber|nullSpread/total line (e.g., -3.5, 220.5)
sportsbookstringSportsbook offering these odds
gamestringHuman-readable game name
sportstringSport identifier (lowercase)
leaguestringLeague identifier
home_teamstring|nullHome team name
away_teamstring|nullAway team name
start_timestring|nullISO 8601 event start time
is_livebooleanWhether the event is currently live
confidence_scorenumberMulti-factor confidence score (0-100)
kelly_fractionnumber|nullKelly criterion optimal bet fraction (0.0 to 1.0)
book_countnumberNumber of sportsbooks offering this market
arb_availablebooleanWhether an arbitrage exists on this market
arb_profitnumber|nullArbitrage profit 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)
possibly_stalebooleantrue if underlying odds may have moved since detection
oldest_odds_age_secondsnumber|nullAge of the stalest odds used in the EV calculation (seconds)
warningsstring[]Data quality warnings (e.g., POTENTIALLY_STALE_ODDS, LIVE_STALE_ODDS)
detected_atstringISO 8601 timestamp when the +EV was first detected

Meta Summary Fields

FieldTypeDescription
summary.countnumberTotal opportunities matching filters
summary.avg_evnumberAverage EV across all results
summary.max_evnumberHighest EV found
summary.by_sportsbookobjectOpportunity count per sportsbook
summary.by_sportobjectOpportunity count per sport
summary.by_marketobjectOpportunity count per market type

Understanding Expected Value

Expected Value (EV) measures the average profit or loss per bet over time. A positive EV (+EV) bet means you have a mathematical edge over the sportsbook.

EV% = (fair_probability x decimal_odds - 1) x 100

Where:

  • fair_probability = No-vig probability derived from the sharp book (Pinnacle)
  • decimal_odds = The decimal odds offered by the soft book

How SharpAPI Calculates EV

SharpAPI uses Pinnacle (a sharp book with efficient odds) as the source of truth for fair probability.

Step 1: Get the sharp book odds

Pinnacle: Team A -115 / Team B +105

Step 2: Remove the vig to find fair probability (Power method)

// Implied probabilities (with vig) probA = 1 / 1.87 = 0.535 // -115 in decimal = 1.87 probB = 1 / 2.05 = 0.488 // +105 in decimal = 2.05 total = 1.023 // 2.3% vig // Power devig: solve for k where probA^k + probB^k = 1 // k ≈ 1.036 for this market fairProbA = 0.535^1.036 = 0.522 (52.2%) fairProbB = 0.488^1.036 = 0.478 (47.8%)

Step 3: Compare to a soft book

DraftKings: Team A -105 (decimal 1.952) Fair probability: 52.3% EV% = (0.523 x 1.952 - 1) x 100 EV% = +2.1%

A +2.1% EV means you expect to profit $2.10 for every $100 wagered on this bet over time.

Why This Works

Book TypeCharacteristics
Sharp (Pinnacle)Low vig, efficient odds, accurate probabilities
Soft (DraftKings, FanDuel, BetMGM)Higher vig, slower to adjust, exploitable

When soft books are slow to update their odds after a market move, their implied probability deviates from reality, creating a +EV opportunity.

EV Thresholds

EV %QualitySuggested Action
< 0%Negative EVAvoid
0 - 2%MarginalOnly viable at high volume
2 - 5%GoodStandard profitable threshold
5%+ExcellentHigh confidence opportunities

We recommend setting min_ev=2 for most use cases. Marginal EV (below 2%) can be eroded by line movement before you place the bet.

Kelly Criterion

The kelly_fraction field tells you the optimal fraction of your bankroll to wager according to the Kelly criterion (0.0 to 1.0, e.g. 0.021 = 2.1%):

Kelly% = (edge / odds_to_1) = (fair_prob x decimal_odds - 1) / (decimal_odds - 1)

Kelly Sizing Guide

Kelly %Risk LevelRecommendation
< 1%LowSmall edge, consider skipping
1 - 3%ModerateStandard bet size
3 - 5%AggressiveStrong edge, but size carefully
5%+Very aggressiveExcellent edge; consider fractional Kelly (half or quarter)

Variance Warning: +EV does not guarantee profit on every bet. Over 100 bets at 5% EV, actual results can range widely. The edge only materializes over hundreds or thousands of bets. Never bet more than you can afford to lose.

Best Practices

  1. Set a minimum EV threshold - Use min_ev=2 or higher to focus on meaningful edges
  2. Use Kelly sizing - Use kelly_fraction to determine bet size (multiply by bankroll)
  3. Filter by confidence - Use confidence_score to prioritize high-confidence opportunities
  4. Monitor market_width - Narrow markets (low width) indicate more efficient pricing and more reliable EV calculations
  5. Act quickly - +EV opportunities are fleeting; lines move fast
  6. Track your results - Log every bet and compare actual ROI to expected EV over time
  7. Use fractional Kelly - Most professionals use quarter or half Kelly to reduce variance
Last updated on