Value Bets V2
Query parameters, response fields, and calculations for /api/value-bets-v2.
GET /api/value-bets-v2 returns grouped player-prop value bets. It is public, allows cross-origin requests, and has no rate limit.
Use the generated endpoint reference for the machine-derived schema. This page explains field semantics.
Use V2
/api/value-bets is the legacy endpoint. New integrations should call /api/value-bets-v2.
Query parameters
All parameters are optional. The default request returns 25 upcoming groups with positive over edge.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
page | integer | 1 | Page number, minimum 1 |
perPage | integer | 25 | Groups per page, 1–100 |
search | string | — | Case-insensitive player or team substring |
marketType | string | — | Market key |
line | number | — | Betting line |
eventIds | CSV integers | — | Match IDs |
uniqueTournamentIds | CSV integers | — | Tournament IDs |
minOdds | number | 0 | Minimum decimal over odds |
maxOdds | number | 0 | Maximum decimal over odds; 0 disables the limit |
source | CSV strings | — | Bookmaker names |
minEV | number | 0 | Minimum over-edge percentage |
maxEV | number | — | Maximum over-edge percentage |
minSources | integer | 0 | Minimum bookmakers offering positive edge |
date | enum | — | today, tomorrow, this-week, or next-week |
specificDate | CSV dates | — | One or more YYYY-MM-DD dates; overrides date |
maxLastGameWithTeam | integer | — | Maximum team games since the player's last 45+ minute appearance |
inPredictedLineup | true | — | Require the player in the predicted lineup |
sortBy | enum | overEdgePercent | overEdgePercent or underEdgePercent |
sortOrder | enum | desc | asc or desc |
superSub | true | — | Add replacement-player stats after a substitution |
Date precedence is specificDate, then date, then upcoming matches. Results exclude NaN edges and default to positive over edge, average edge descending, then match date ascending.
Response
{
"data": [],
"pagination": {
"currentPage": 1,
"totalPages": 12,
"totalCount": 291,
"hasNextPage": true,
"hasPreviousPage": false
}
}Each data item groups one (playerId, marketType, line, matchId) combination.
Group fields
| Field | Type | Meaning |
|---|---|---|
groupKey | string | {playerId}_{marketType}_{line}_{matchId} |
playerId, playerName | integer, string | Player identity |
teamId, teamName | integer, string | Player's team |
matchId, matchDate | integer | Match ID and Unix start time in seconds |
marketType, line | string, number | Prop market and line |
matchSlug | string or null | Match URL slug |
homeTeamId, homeTeamName | integer/string or null | Home team |
awayTeamId, awayTeamName | integer/string or null | Away team |
models | array | Model fair odds |
bookmakers | array | Bookmaker odds, highest overOdds first |
avgOverEdge | number or null | Average model × bookmaker over edge |
bestOverOdds | number or null | Highest bookmaker over odds |
matchOdds | object or null | Bet365 1x2 odds |
last30Stats | number[] | Starter-game values, newest first |
sampleSize | integer | Available starter games, up to 30 |
hitRates | object | L10, L20, and L30 percentages |
recentGames | array | Starter games with opponent and position context |
activityInfo | object or null | Recent activity and predicted-lineup state |
Nested fields
| Object | Fields |
|---|---|
models[] | modelName, fairOverOdds, fairUnderOdds, opponentMultiplier |
bookmakers[] | source, overOdds, underOdds |
matchOdds | home, draw, away; Bet365 only |
hitRates | l10, l20, l30; integer percentages or null |
recentGames[] | stat, minutesPlayed, position, isHome, opponentId, opponentName, uniqueTournamentId, hasSuperSub |
activityInfo | startedLastGame, lastGameWithTeam, inPredictedLineup |
lastGameWithTeam=0 means the player appeared for 45+ minutes in the team's latest game. A null activityInfo means activity data could not be resolved.
Market types
| Key | Label | Statistic |
|---|---|---|
onTargetScoringAttempt | Shots on Target | shotsOnTarget |
shots | Shots | On-target + off-target + blocked |
goals | Goals | goals |
totalTackle | Tackles | tackles |
fouls | Fouls Committed | fouls |
wasFouled | Fouls Won | wasFouled |
totalPass | Passes | totalPasses |
yellowCard | Yellow Cards | yellowCards |
Other database values may lack a display label.
Calculations
Edge
edge = ((bookmakerOdds / modelFairOdds) - 1) * 100avgOverEdge averages all valid model × bookmaker combinations. bestOverOdds is the highest bookmaker price. Calculate a per-model edge by pairing that price with each model's fairOverOdds.
Hit rates
For windows of 10, 20, and 30 starter games:
hit rate = count(stat >= line) / available games * 100The API rounds to an integer and returns null when the window has no games.
Super Sub
With superSub=true, the API adds the replacement player's stat to the starter's stat after a substitution. Combined games set recentGames[].hasSuperSub=true; last30Stats and hit rates use the combined value.
Differences from V1
| Behavior | V1 | V2 |
|---|---|---|
| Hit-rate windows | L10/L20/L40 | L10/L20/L30 |
| History | 40 games | 30 starter games |
| Match odds | Bookmaker average | Bet365 |
| Super Sub | Client-side | superSub=true |
| Event parameter | eventId | eventIds |
| Tournament parameter | uniqueTournamentId | uniqueTournamentIds |
| Odds parameters | minOdd, maxOdd | minOdds, maxOdds |
Examples
# Upcoming bets
GET /api/value-bets-v2
# Player search
GET /api/value-bets-v2?search=salah
# Premier League, odds 1.5–3.0
GET /api/value-bets-v2?uniqueTournamentIds=17&minOdds=1.5&maxOdds=3
# Shots on target with Super Sub
GET /api/value-bets-v2?marketType=onTargetScoringAttempt&line=0.5&superSub=true
# Today's Bet365 bets with at least 5% edge
GET /api/value-bets-v2?date=today&source=Bet365&minEV=5
# Predicted-lineup players with at least 5% edge
GET /api/value-bets-v2?inPredictedLineup=true&minEV=5&perPage=10Discover current markets, lines, bookmakers, events, and tournaments through:
GET /api/value-bets?action=filter-optionsErrors and timestamps
matchDate is a Unix timestamp in seconds. In JavaScript, use new Date(matchDate * 1000).
{ "error": "Method not allowed" }Wrong methods return 405. Server failures return 500 with {"error":"Internal server error"}.