Tips & Predictions API endpoints
AI-generated betting tips with confidence scores and historical accuracy tracking.
4 of 4 endpoints · all categories · get a free API key
GET/api/v1/predictions→ alias of /api/v1/tipsFree tier
Deprecated alias of /api/v1/tips.
QUIRK: the file's own doc-comment claims it "proxies to tips with a sport_key=soccer filter for backwards compatibility", but the actual code is a bare re-export (`export { GET, OPTIONS } from '../tips/route'`) — NO soccer filter is applied; it is byte-identical behaviour to /api/v1/tips, all sports included. Comment is stale/misleading. Marked deprecated 2026-08-06, "will be removed in a future version" (no removal date set as of 2026-09-03). Same params/response/tier as /api/v1/tips.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| sport_key | string | No | – | Same as /api/v1/tips — filters by sport key despite the doc-comment implying a fixed soccer filter (that filter does not actually exist in code). |
| min_confidence | integer | No | 1 | Same as /api/v1/tips. |
| limit | integer | No | 50 | Same as /api/v1/tips. |
| include_settled | boolean | No | false | Same as /api/v1/tips. |
curl \
-H "X-API-Key: YOUR_KEY" \
"https://krokodds.com.au/api/v1/predictions?sport_key=aussierules_afl""identical shape to /api/v1/tips — see that entry"GET/api/v1/predictions/confidenceFree tier
Model confidence breakdown across racing, sports, and player props, plus 30-day historical accuracy by confidence bucket.
Gates on the 'tips' feature (tierAllowsFeature(tier,'tips')) even though the path is under /predictions. `force-dynamic`/`revalidate=0` — NOT cached via unstable_cache (response header still claims `Cache-Control: public, max-age=300` which is misleading given no server cache). Sports and props predictions are ONLY loaded if `sport`/`event_id` params are respectively provided — with type=all and neither param, only racing predictions populate. `summary.breakdown` is always `{}` in the current code (allBreakdowns is declared but never populated — dead aggregation). historicalAccuracy tries the primary store the settled-tips store first, falls back to the secondary store. A read that fails is never served as "no predictions": the three feeds report failure two ways (`available:false` from the loader's own swallow, or a thrown read) and both are named in `meta.failed_sources`; if every requested feed failed the route answers 503 + Retry-After: 30 with Cache-Control: no-store instead of a 200 with an empty list, and a partial failure is answered 200 but switched to `private, no-store` so a thin payload is never cached as a complete one; the historical-accuracy arm is additive and is named rather than fatal. An ENRICHMENT read inside a feed is named the same way and does not drop that feed's predictions: the sports arm reports the injury feed it could not read (`injury_data`) through `failedSources` while still serving the predictions it did read, so a scored prediction is never served as if the input it was scored on had been neutral.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| type | string | No | all | "racing" | "sports" | "props" | "all". Lowercased. |
| sport | string | No | – | Sport key — required for the sports branch to run (ignored if type excludes sports). |
| date | string | No | today (AU) | YYYY-MM-DD — racing branch only. |
| event_id | string | No | – | Specific event id — required for the props branch to run. |
| limit | integer | No | 50 | Max predictions per type-branch; capped 20 (free) / 200 (api). |
curl \
-H "X-API-Key: YOUR_KEY" \
"https://krokodds.com.au/api/v1/predictions/confidence?type=all"{
"success": true,
"meta": {
"type": "racing",
"sport": null,
"date": "2026-09-03",
"eventId": null,
"generatedAt": "2026-09-03T04:00:00.000Z",
"cacheTtl": 300
},
"summary": {
"overallConfidence": 0.74,
"breakdown": {},
"dataSources": [
"racing_form",
"sectionals",
"barrier_trial",
"weather"
],
"historicalAccuracy": {
"totalPredictions": 812,
"correctPredictions": 471,
"accuracyRate": 0.58,
"byConfidenceBucket": {
"high": {
"total": 210,
"correct": 148,
"rate": 0.7
},
"medium": {
"total": 380,
"correct": 218,
"rate": 0.57
},
"low": {
"total": 222,
"correct": 105,
"rate": 0.47
}
}
}
},
"predictions": [
{
"id": "racing-Written By-R6",
"type": "racing",
"confidence": 0.81,
"dataSources": [
"racing_form",
"sectionals",
"barrier_trial"
],
"breakdown": {
"weather": 0.6,
"barrier": 0.75,
"sectionals": 0.88,
"pedigree": 0.55,
"ensemble": 0.81
},
"reasoning": "Strong recent sectionals and barrier draw at Flemington R6."
}
]
}GET/api/v1/tipsFree tier
In-house model tips/predictions across all covered sports (active by default, or settled history with include_settled=true).
Uses the OLDER hand-rolled auth preamble (not the standard auth guard/the standard v1 route factory) — no explicit credit-cost debit in this file, API-key verification called with default cost. Merges canonical the tips engine engine picks over legacy the legacy tips engine (canonical wins on conflicting fixtures; legacy only fills 7 leagues the engine doesn't cover) — active-tips path only, not for include_settled=true which reads the settled-tips store directly. Free tier cache 120s, api tier 60s (the declared 30s api window is raised to the 60s v1Revalidate floor). Free tier capped at 50 rows/request, api tier 1000.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| sport_key | string | No | – | Filter by sport key. Alias: `sport`. Lowercased. |
| min_confidence | integer | No | 1 | Minimum confidence 1-5, clamped. |
| limit | integer | No | 50 | Max rows; capped 50 (free) / 1000 (api) by getMaxLimit(). |
| include_settled | boolean | No | false | "true" to return the settled-tips store history (with resolution/actual_winner) instead of pending active tips. |
curl \
-H "X-API-Key: YOUR_KEY" \
"https://krokodds.com.au/api/v1/tips?sport_key=aussierules_afl"{
"success": true,
"data": [
{
"id": "aussierules_afl-geelong-carlton-20260906t0740",
"event_id": "e_afl_20260906_gee_car",
"sport_key": "aussierules_afl",
"sport": "AFL",
"home_team": "Geelong Cats",
"away_team": "Carlton Blues",
"commence_time": "2026-09-06T07:40:00.000Z",
"pick": "Geelong Cats -12.5",
"pick_side": "home",
"confidence": 4,
"confidence_label": "High",
"consensus_prob_home": 0.71,
"consensus_prob_away": 0.29,
"predicted_margin": 18.4,
"predicted_margin_side": "home",
"resolution": "pending",
"actual_winner": null
}
],
"meta": {
"count": 1,
"tier": "free",
"limit": 50,
"requested_limit": 50,
"include_settled": false,
"timestamp": "2026-09-03T04:00:00.000Z",
"rate_limit": {
"limit": 50,
"remaining": 949,
"reset": "2026-10-01T00:00:00.000Z"
}
}
}GET/api/v1/tips/accuracyFree tier
Historical hit-rate / track-record for the tips model, overall and broken down by confidence bucket, optionally scoped to one sport.
Reads model_track_record. Per-sport lookup filters on the `sport_key` column (indexed); the unscoped (all-sport) query has no column for `total` (lives in JSONB) so it sorts in memory after fetching up to `scanSize` (min(limit,100)) rows — an all-sports call is NOT a true global ranking beyond that scan window. Same free/api cache tiers as /tips (300s/120s, both above the 60s floor).
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| sport_key | string | No | – | Filter to one sport. Alias: `sport`. Lowercased. |
| limit | integer | No | 50 | Max rows; capped 50 (free) / 1000 (api). |
curl \
-H "X-API-Key: YOUR_KEY" \
"https://krokodds.com.au/api/v1/tips/accuracy?sport_key=aussierules_afl"{
"success": true,
"data": [
{
"sport_key": "rugbyleague_nrl",
"wins": 142,
"losses": 88,
"pushes": 3,
"total": 233,
"decided": 230,
"hit_rate": 0.6174,
"by_confidence": [
{
"confidence": "3",
"wins": 51,
"losses": 44,
"pushes": 1,
"total": 96,
"hit_rate": 0.5368
},
{
"confidence": "4",
"wins": 63,
"losses": 32,
"pushes": 1,
"total": 96,
"hit_rate": 0.6632
},
{
"confidence": "5",
"wins": 28,
"losses": 12,
"pushes": 1,
"total": 41,
"hit_rate": 0.7
}
],
"last_settled_at": "2026-09-02T22:30:00.000Z",
"updated_at": "2026-09-02T22:31:00.000Z"
}
],
"meta": {
"count": 1,
"tier": "free",
"limit": 50,
"requested_limit": 50,
"sport_key": "rugbyleague_nrl",
"timestamp": "2026-09-03T04:00:00.000Z",
"rate_limit": {
"limit": 50,
"remaining": 949,
"reset": "2026-10-01T00:00:00.000Z"
}
}
}Other categories
Per-event head-to-head odds, alternate lines, best prices across books, player props, live state and AI-generated summaries.
Krok's built-in scanners — arbitrage, positive EV, middles, low-holds, player props and same-game multi (SGM) picks, already devigged against a blended sharp baseline.
The full Australian racing stack — thoroughbred, harness and greyhound. Meetings and runner fields, form, sectionals, ratings, market movers, exchange arbs, tote pools and results.
Raw per-bookmaker prices as scraped, before any analysis layer. `/scraped-odds/*` paths are aliases of the equivalent `/odds-feed/*` route.
Sport reference data, team form guides, league standings, injury reports and weather-impact analysis.
Ranked leaderboards built on top of the stat feeds — per-sport player leaders for a chosen stat, season and view.
ATP/WTA rankings, upcoming fixtures, match results, Elo ratings and surface-specific stats.
Deep archives — player and team game logs, shot charts, AFL/NRL historical data. Paid API plan only.
Static lookup data for building your own UI — players, venues, headshots, team logos and sport/league metadata.
Cricket, cycling, esports, Formula 1, golf, MMA, boxing, NFL and soccer coverage beyond the AU staples.
Account and billing endpoints, bulk export, SSE streaming, webhook management and API health.
Odds history, steam-move detection, player prop stats/results, injuries, weather and other supporting feeds.
Polymarket and Kalshi sentiment plus a universal prediction-market catalogue and resolutions feed.