Properties
| Name | Type | Description |
|---|---|---|
| id | string | 16-character hex opportunity ID |
| game_id | stringnull | |
| ev_percentage | number | Expected value as a percentage (e.g., 4.2 = 4.2% EV) |
| odds_american | number | |
| odds_decimal | number | |
| no_vig_odds | numbernull | Fair odds with vig removed |
| selection | string | |
| market | string | |
| line | numbernull | |
| is_alternate_line | boolean | True when this row's `line` differs from the best-effort main line for its cohort. A cohort is (event, market_type, selection axis), resolved per sportsbook: the selection axis is the player for playe |
| sportsbook | string | Sportsbook offering these odds. Multiple entries may exist for the same selection if several books are +EV. |
| game | string | |
| sport | string | |
| league | string | |
| home_team | stringnull | |
| away_team | stringnull | |
| start_time | stringnull | |
| is_live | boolean | |
| market_width | numbernull | Spread between best and worst odds across books |
| fair_probability | numbernull | No-vig (devigged) fair probability (0.0 to 1.0) |
| devig_method | string | Method used to remove vig |
| sharp_book | string | Sharp book used as reference (e.g., pinnacle) |
| external_event_id | stringnull | Sportsbook-native event ID for deep linking |
| selection_id | stringnull | Sportsbook outcome/selection ID for bet-level deep links |
| detected_at | string | |
| confidence_score | number | Multi-factor confidence score (0-100) |
| kelly_percent | numbernull | Optimal bet fraction (0.0-1.0) from Kelly criterion |
| book_count | integer | Number of books offering this market |
| arb_available | boolean | Whether an arbitrage opportunity exists for this market |
| arb_profit | numbernull | Arbitrage profit percentage if available |
| is_player_prop | boolean | |
| player_name | stringnull | |
| player_id | stringnull | Canonical cross-book player identifier resolved by atlas_players (e.g. "baseball_mlb_corbin_carroll"). null when the producer has not resolved a canonical id for this player — group on `player_id` and |
| stat_category | stringnull | |
| possibly_stale | boolean | Whether the odds may be stale |
| oldest_odds_age_seconds | numbernull | Age of the oldest odds used in this calculation |
| warnings | array | Data-quality warning flags. The EV engine emits exactly four: LIVE_STALE_ODDS (live, and the oldest odds used are more than 30s old), STALE_PREMATCH_ODDS (prematch, and the bet-side price has not move |
| quality_tier | string | Grader-certified quality label. A = ev_percentage >= 4 (>= 6 for player props), Pinnacle-anchored (sharp_book = pinnacle), prematch (is_live = false), and the (book, sport, market) segment is unflagge |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/api-evangelist/sharpapi/main/json-schema/sharpapi-evopportunity-schema.json",
"title": "EVOpportunity",
"x-generated": "2026-10-14",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/sharpapi-openapi.json#/components/schemas/EVOpportunity",
"type": "object",
"required": [
"id",
"game_id",
"ev_percentage",
"odds_american",
"odds_decimal",
"no_vig_odds",
"selection",
"market",
"line",
"sportsbook",
"game",
"sport",
"league",
"home_team",
"away_team",
"start_time",
"is_live",
"market_width",
"fair_probability",
"devig_method",
"sharp_book",
"external_event_id",
"selection_id",
"detected_at",
"confidence_score",
"kelly_percent",
"book_count",
"arb_available",
"arb_profit",
"is_player_prop",
"player_name",
"player_id",
"stat_category",
"possibly_stale",
"oldest_odds_age_seconds",
"warnings"
],
"properties": {
"id": {
"type": "string",
"description": "16-character hex opportunity ID"
},
"game_id": {
"type": [
"string",
"null"
]
},
"ev_percentage": {
"type": "number",
"description": "Expected value as a percentage (e.g., 4.2 = 4.2% EV)"
},
"odds_american": {
"type": "number"
},
"odds_decimal": {
"type": "number"
},
"no_vig_odds": {
"type": [
"number",
"null"
],
"description": "Fair odds with vig removed"
},
"selection": {
"type": "string"
},
"market": {
"type": "string"
},
"line": {
"type": [
"number",
"null"
]
},
"is_alternate_line": {
"type": "boolean",
"description": "True when this row's `line` differs from the best-effort main line for its cohort. A cohort is (event, market_type, selection axis), resolved per sportsbook: the selection axis is the player for player-prop markets, the team side for spread and team-total markets, and the raw selection everywhere else. Always false for markets with no line (moneyline, outright). The live endpoint always emits this field; it was absent from this schema until spec 3.9.0."
},
"sportsbook": {
"type": "string",
"description": "Sportsbook offering these odds. Multiple entries may exist for the same selection if several books are +EV."
},
"game": {
"type": "string"
},
"sport": {
"type": "string"
},
"league": {
"type": "string"
},
"home_team": {
"type": [
"string",
"null"
]
},
"away_team": {
"type": [
"string",
"null"
]
},
"start_time": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"is_live": {
"type": "boolean"
},
"market_width": {
"type": [
"number",
"null"
],
"description": "Spread between best and worst odds across books"
},
"fair_probability": {
"type": [
"number",
"null"
],
"description": "No-vig (devigged) fair probability (0.0 to 1.0)"
},
"devig_method": {
"type": "string",
"description": "Method used to remove vig"
},
"sharp_book": {
"type": "string",
"description": "Sharp book used as reference (e.g., pinnacle)"
},
"external_event_id": {
"type": [
"string",
"null"
],
"description": "Sportsbook-native event ID for deep linking"
},
"selection_id": {
"type": [
"string",
"null"
],
"description": "Sportsbook outcome/selection ID for bet-level deep links"
},
"detected_at": {
"type": "string",
"format": "date-time"
},
"confidence_score": {
"type": "number",
"description": "Multi-factor confidence score (0-100)"
},
"kelly_percent": {
"type": [
"number",
"null"
],
"description": "Optimal bet fraction (0.0-1.0) from Kelly criterion"
},
"book_count": {
"type": "integer",
"description": "Number of books offering this market"
},
"arb_available": {
"type": "boolean",
"description": "Whether an arbitrage opportunity exists for this market"
},
"arb_profit": {
"type": [
"number",
"null"
],
"description": "Arbitrage profit percentage if available"
},
"is_player_prop": {
"type": "boolean"
},
"player_name": {
"type": [
"string",
"null"
]
},
"player_id": {
"type": [
"string",
"null"
],
"description": "Canonical cross-book player identifier resolved by atlas_players (e.g. \"baseball_mlb_corbin_carroll\"). null when the producer has not resolved a canonical id for this player — group on `player_id` and fall back to `player_name`. Player-prop markets only."
},
"stat_category": {
"type": [
"string",
"null"
]
},
"possibly_stale": {
"type": "boolean",
"description": "Whether the odds may be stale"
},
"oldest_odds_age_seconds": {
"type": [
"number",
"null"
],
"description": "Age of the oldest odds used in this calculation"
},
"warnings": {
"type": "array",
"items": {
"type": "string"
},
"description": "Data-quality warning flags. The EV engine emits exactly four: LIVE_STALE_ODDS (live, and the oldest odds used are more than 30s old), STALE_PREMATCH_ODDS (prematch, and the bet-side price has not moved in more than 60 minutes while the feed is still alive; the row is served with possibly_stale: true), SINGLE_SHARP_REF (only one sharp book priced the market, so the fair probability is uncorroborated), SINGLE_SHARP_PERIOD (the single-sharp subset that is also a period/derivative sub-slice). The key is always present and never null (it is listed in required); it is an empty array [] when none apply. LOW_IMPLIED_TOTAL and POTENTIALLY_STALE_ODDS are arbitrage-only flags and are never emitted here — see ArbitrageOpportunity.warnings."
},
"quality_tier": {
"type": "string",
"enum": [
"A",
"B",
"C"
],
"description": "Grader-certified quality label. A = ev_percentage >= 4 (>= 6 for player props), Pinnacle-anchored (sharp_book = pinnacle), prematch (is_live = false), and the (book, sport, market) segment is unflagged by the nightly reliability model — the only class with consistently positive graded ROI. B = ev_percentage >= 2 (>= 4 props) and the segment is not exclusion-flagged; includes live, non-Pinnacle-anchored, and watch-flagged rows that clear the band. C = everything else, plus any exclusion-flagged segment regardless of EV (disclosed as market intelligence, not a pick). A high ev_percentage alone does not imply A — the sharp anchor, prematch/live state, and the segment-reliability model also gate it. Omitted on suspended rows (is_suspended)."
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/sharpapi-evopportunity"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.