StatsHub Docs
APIGeneral

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.

ParameterTypeDefaultMeaning
pageinteger1Page number, minimum 1
perPageinteger25Groups per page, 1–100
searchstringCase-insensitive player or team substring
marketTypestringMarket key
linenumberBetting line
eventIdsCSV integersMatch IDs
uniqueTournamentIdsCSV integersTournament IDs
minOddsnumber0Minimum decimal over odds
maxOddsnumber0Maximum decimal over odds; 0 disables the limit
sourceCSV stringsBookmaker names
minEVnumber0Minimum over-edge percentage
maxEVnumberMaximum over-edge percentage
minSourcesinteger0Minimum bookmakers offering positive edge
dateenumtoday, tomorrow, this-week, or next-week
specificDateCSV datesOne or more YYYY-MM-DD dates; overrides date
maxLastGameWithTeamintegerMaximum team games since the player's last 45+ minute appearance
inPredictedLineuptrueRequire the player in the predicted lineup
sortByenumoverEdgePercentoverEdgePercent or underEdgePercent
sortOrderenumdescasc or desc
superSubtrueAdd 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

FieldTypeMeaning
groupKeystring{playerId}_{marketType}_{line}_{matchId}
playerId, playerNameinteger, stringPlayer identity
teamId, teamNameinteger, stringPlayer's team
matchId, matchDateintegerMatch ID and Unix start time in seconds
marketType, linestring, numberProp market and line
matchSlugstring or nullMatch URL slug
homeTeamId, homeTeamNameinteger/string or nullHome team
awayTeamId, awayTeamNameinteger/string or nullAway team
modelsarrayModel fair odds
bookmakersarrayBookmaker odds, highest overOdds first
avgOverEdgenumber or nullAverage model × bookmaker over edge
bestOverOddsnumber or nullHighest bookmaker over odds
matchOddsobject or nullBet365 1x2 odds
last30Statsnumber[]Starter-game values, newest first
sampleSizeintegerAvailable starter games, up to 30
hitRatesobjectL10, L20, and L30 percentages
recentGamesarrayStarter games with opponent and position context
activityInfoobject or nullRecent activity and predicted-lineup state

Nested fields

ObjectFields
models[]modelName, fairOverOdds, fairUnderOdds, opponentMultiplier
bookmakers[]source, overOdds, underOdds
matchOddshome, draw, away; Bet365 only
hitRatesl10, l20, l30; integer percentages or null
recentGames[]stat, minutesPlayed, position, isHome, opponentId, opponentName, uniqueTournamentId, hasSuperSub
activityInfostartedLastGame, 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

KeyLabelStatistic
onTargetScoringAttemptShots on TargetshotsOnTarget
shotsShotsOn-target + off-target + blocked
goalsGoalsgoals
totalTackleTacklestackles
foulsFouls Committedfouls
wasFouledFouls WonwasFouled
totalPassPassestotalPasses
yellowCardYellow CardsyellowCards

Other database values may lack a display label.

Calculations

Edge

edge = ((bookmakerOdds / modelFairOdds) - 1) * 100

avgOverEdge 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 * 100

The 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

BehaviorV1V2
Hit-rate windowsL10/L20/L40L10/L20/L30
History40 games30 starter games
Match oddsBookmaker averageBet365
Super SubClient-sidesuperSub=true
Event parametereventIdeventIds
Tournament parameteruniqueTournamentIduniqueTournamentIds
Odds parametersminOdd, maxOddminOdds, 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=10

Discover current markets, lines, bookmakers, events, and tournaments through:

GET /api/value-bets?action=filter-options

Errors 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"}.

On this page