Krok Odds API
Real-time arbitrage, positive EV, middle, and racing edge data for Australian sports markets — updated every few minutes across 140+ bookmakers.
⚡ Quick Start (5 Minutes)
Get Your API Key
Visit /api-dashboard and click "Create API Key". Copy the key — you'll need it for authentication.
Make Your First Request
curl https://krokodds.com.au/api/v1/opportunities/arbitrage?limit=5 \ -H "X-API-Key: YOUR_API_KEY_HERE"
Parse the Response
You'll receive a JSON response with arbitrage opportunities:
{
"success": true,
"data": [
{
"id": "arb_abc123",
"sport": "NBA",
"event": "Lakers vs Warriors",
"value": 2.3,
"bookmaker1": "Bet365",
"odds1": 2.10,
"bookmaker2": "Sportsbet",
"odds2": 2.05
}
],
"meta": {
"count": 1,
"timestamp": "2026-03-02T10:30:00Z"
}
}Build Your App!
You now have access to real-time betting opportunities. Build an arb alert bot, value betting dashboard, or integrate into your existing tools.
Postman Collection
Import our pre-configured Postman collection to test all endpoints instantly. Includes all query parameters and example responses.
Overview
Krok Odds scans 140+ bookmakers every few minutes across 156 sports — AFL, NRL, NBA, NFL, EPL, soccer, cricket, tennis, F1, golf, cycling, boxing, MMA, esports, and more. It identifies three types of edge:
- Arbitrage (arbs):Two bookmakers price the same event so differently that you can bet both sides and guarantee profit regardless of the result. ROI is typically 1–8%.
- Positive EV (snipes):One bookmaker's odds are higher than the mathematically "fair" price derived from the sharp exchange line. Over a large sample, these bets return profit.
- Middles:Totals or spreads lines differ enough across books that you can cover both sides. If the result lands in the window between lines, both legs win.
- Racing edge:Best fixed-odds across AU books vs the licensed exchange lay price. Available in the web dashboard and via the /v1/racing/* API endpoints (arbs, movers, meetings, results, runner-form, ratings, runner-stats, connections).
Beyond edge detection, the API also provides: player props with historical hit rates, same-game multi (SGM) suggestions, ML-driven game picks with confidence scores, injury feeds, head-to-head records, best-price snapshots, advanced sports statistics (14 multiplexed datasets), exchange pricing (5 sources), closing-line value analysis, SSE real-time streaming, sport-specific data (golf rankings & skills, cycling riders & startlists, esports teams & leagues, cricket innings, tennis matches, F1 races), prediction markets (Polymarket & Kalshi), reference data (player profiles, team logos, venue info), and a redistributable direct-scrape odds feed.
All data is computed server-side by our proprietary scanning engine. Once prices are collected, the sharpest available exchange line is used as the fair-price benchmark — if a bookie beats that implied fair price after commission, that's a snipe. If two bookies combined imply <100% probability, that's an arb.
Bookmaker Coverage
Every book Krok Odds prices, across all feeds — licensed odds aggregators, betting-exchange feeds, and the major AU aggregator platforms. Clone brands on a white-label platform share one odds line (coverage breadth, not extra prices), so the API dedupes them to a single priced line. Expand a platform row to see every brand it covers.
Named bookmakers
Aggregator platforms
Each platform powers many white-label betting sites that all publish the same odds line. Expand a row to see every brand it covers.
Authentication
All API requests require an API key. You can pass it as a query parameter or as an HTTP header. Headers are preferred — they don't show up in server logs or browser history.
GET /api/v1/opportunities?type=arbs X-API-Key: krok_live_xxxxxxxxxxxxxxxx
GET /api/v1/opportunities?type=arbs&apikey=krok_live_xxxxxxxxxxxxxxxx
sport (human label like AFL) or sport_key (internal sport key like aussierules_afl). Use GET /v1/sports to see all active sport keys.Rate Limit Headers
Every response includes these headers:
| Header | Description |
|---|---|
| X-RateLimit-Tier | Your plan tier (free / api) |
| X-RateLimit-Limit | Max results per request for your tier |
| X-RateLimit-Remaining | Requests remaining this month |
| X-RateLimit-Reset | Date your monthly quota resets |
GET /api/v1/opportunities
The main endpoint. Returns arbs, EV snipes, middles, low holds, racing edges, and player props — all filtered and sorted by value. Results are cached server-side for 5 minutes.
GET https://krokodds.com.au/api/v1/opportunities
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| type | string | required | all | Which opportunity type to return. One of: all · arbs · snipes · middles · low_holds · racing · playerprops. positive-ev is accepted as an alias for snipes. |
| sport | string | optional | (all sports) | Filter by sport label (e.g. AFL, NBA, NRL, EPL). Case-insensitive. |
| sport_key | string | optional | (none) | Filter by internal sport key (e.g. aussierules_afl, basketball_nba). More precise than sport — use this when targeting a specific league. |
| minvalue | number | optional | 0 | Minimum edge / ROI % to include. e.g. 2.0 returns only arbs ≥2% ROI. |
| limit | integer | optional | 100 | Max results per type. Capped by tier: Free=100, API=500. |
| apikey | string | optional | — | Your API key. Prefer X-API-Key header instead. |
Quick start
curl -G "https://krokodds.com.au/api/v1/opportunities" \ -H "X-API-Key: YOUR_API_KEY" \ --data-urlencode "type=arbs" \ --data-urlencode "minvalue=2.0" \ --data-urlencode "limit=20"
Dedicated Opportunity Endpoints
Each opportunity type also has a dedicated endpoint. They return the same object fields as the aggregated /opportunities?type=… call, but the wrapper is a flat {"data":[...]} array (cursor-paginated, fields= projection supported) instead of the keyed {"data":{"<type>":[...]}} map.
| Endpoint | Aggregated equivalent | Tier · Cache |
|---|---|---|
| /api/v1/opportunities/arbitrage | ?type=arbs | All tiers · 300s |
| /api/v1/opportunities/low-holds | ?type=low_holds | All tiers · 300s |
| /api/v1/opportunities/positive-ev | ?type=snipes | All tiers · 300s |
| /api/v1/opportunities/middles | ?type=middles | All tiers · 300s |
| /api/v1/opportunities/player-props | ?type=playerprops | All tiers · see below |
Dedicated Endpoint Filters
All filters compose with AND logic. The bookmaker filter is a case-insensitive substring match. Active filters are echoed back under meta.filters.
/opportunities/arbitrage — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport (e.g. basketball_nba) |
| sport | string | — | Filter by sport label (e.g. NBA) |
| bookmaker | string | — | Filter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2. |
| min_value | number | 0 | Minimum edge/ROI % |
| limit | integer | 100 | Max results (cap 10000) |
| cursor | string | — | Pagination cursor |
| fields | string | — | Comma-separated fields to include |
/opportunities/positive-ev — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport (e.g. basketball_nba) |
| sport | string | — | Filter by sport label (e.g. NBA) |
| bookmaker | string | — | Filter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2. |
| min_value | number | 0 | Minimum edge/ROI % |
| limit | integer | 100 | Max results (cap 10000) |
| cursor | string | — | Pagination cursor |
| fields | string | — | Comma-separated fields to include |
/opportunities/low-holds — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport (e.g. basketball_nba) |
| sport | string | — | Filter by sport label (e.g. NBA) |
| bookmaker | string | — | Filter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2. |
| min_value | number | 0 | Minimum edge/ROI % |
| max_hold | number | — | Maximum hold % to include |
| limit | integer | 100 | Max results (cap 10000) |
| cursor | string | — | Pagination cursor |
| fields | string | — | Comma-separated fields to include |
/opportunities/middles — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport (e.g. basketball_nba) |
| sport | string | — | Filter by sport label (e.g. NBA) |
| bookmaker | string | — | Filter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2. |
| min_value | number | 0 | Minimum edge/ROI % |
| limit | integer | 100 | Max results (cap 10000) |
| cursor | string | — | Pagination cursor |
| fields | string | — | Comma-separated fields to include |
/opportunities/player-props — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport |
| player | string | — | Filter by player name (substring match) |
| bookmaker | string | — | Filter by bookmaker |
| market | string | — | Filter by market type |
| min_ev | number | 0 | Minimum EV percentage |
| limit | integer | 100 | Max results |
/opportunities/sgm-picks — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport |
| tier | string | — | Risk tier (safe/balanced/aggressive) |
| min_confidence | number | — | Minimum confidence (1-5) |
| limit | integer | — | Max results |
Racing
Australian thoroughbred (T), harness (H), and greyhound (G) coverage. Eight live endpoints: arbs, movers, meetings, results, runner-form, ratings, runner-stats, and connections. Four data products: tote-pools, sectionals, odds-history, and results/{date}.
GET /api/v1/racing/arbs
Two-leg racing arbitrage records. Filter by venue, race type, and minimum edge.
GET /api/v1/racing/arbs?race_type=T&venue=randwick&minedge=2&limit=20
Params: venue (substring), race_type (T|H|G), minedge (number, default 0), limit (Cap: 500).
{
"success": true,
"data": [
{
"id": "flemington_r4_horse_7",
"venue": "Flemington",
"race_number": 4,
"race_name": "TAB Handicap",
"race_type": "T",
"jump_time": "2026-03-01T05:10:00Z",
"runner": "Gatwick",
"arb_type": "each-way-arb",
"leg1_bookmaker": "Sportsbet",
"leg1_odds": 6.5,
"leg2_bookmaker": "Betfair",
"leg2_odds": 1.68,
"edge": 2.41,
"stake1_pct": 20.52,
"stake2_pct": 79.48,
"all_legs": null,
"detected_at": "2026-03-01T04:59:10Z"
}
],
"meta": {
"count": 1,
"tier": "api",
"limit": 50,
"requested_limit": 50,
"timestamp": "2026-03-01T05:00:00Z"
}
}arb_type: win-arb (two AU bookmakers on the win market) or each-way-arb (win at one book vs place at another). all_legs is populated only for multi-leg constructions and is null for the two-leg default.
GET /api/v1/racing/movers
Steamers (shortening) and drifters (lengthening) merged into a single response.
GET /api/v1/racing/movers?movement_type=steamer&race_type=T&min_movement=10&limit=20
Params: venue, race_type (T|H|G), movement_type (steamer|drifter), min_movement (%, default 0), limit (Cap: 500).
GET /api/v1/racing/meetings
Today's meetings + full race cards. Each meeting includes BOM weather observation, BOM 7-day forecast, track condition hint, tote_jurisdiction, andraces[] with runner-level fields (barrier, jockey, trainer, weight, form, finishing position for resulted races, scratchings, top-of-book win/place, and a per-bookmaker odds[] grid). Filter to a single state with jurisdiction (alias state).
GET /api/v1/racing/meetings?race_type=T&jurisdiction=NSW&limit=50
Params: race_type (T|H|G), venue (substring), jurisdiction (AU state code, alias state), limit (Cap: 500). Cache TTL 300 seconds. See Racing meeting object below for the full field reference.
GET /api/v1/racing/tote-pools
Per-race totalisator pool totals, jackpots, status and paid dividends, plus exotic (multi-leg) pools.
GET /api/v1/racing/tote-pools?date=2026-08-03&venue=randwick
Params: date (YYYY-MM-DD, default today Sydney), venue (optional). Returns { date, venue, pools: [{ race, number, pools: [{ product, poolTotal, jackpot, status, dividends: [{ selections, amount }] }], exoticPools: [{ product, poolTotal, jackpot, legs }] }] }.
GET /api/v1/racing/sectionals/{horseCode}
Aggregated sectional splits and speed metrics for a single runner, plus a career/form profile.
GET /api/v1/racing/sectionals/{horseCode}Params: horseCode (path — the horse_code field from a runner in the meetings response). Returns { horse_code, name, sectionals: { run_count, l600, l400, l200, speed: { early, mid, late, overall, peak }, closing_ratio }, profile: { condition_splits, first_up, second_up, third_up, winning_range, days_since_last_win, career_stats, sire_progeny_dry, sire_progeny_wet } }.
GET /api/v1/racing/odds-history
Full price-fluctuation history per runner for a single race, with starting price and exchange starting price.
GET /api/v1/racing/odds-history?date=2026-08-03&venue=randwick&raceNumber=5
Params: date (YYYY-MM-DD), venue, raceNumber (integer). Each item: { runner, number, name, flucs: [{ timestamp, odds }], bookFlucs, sp, bsp }.
bookFlucs — per-bookmaker price fluctuation curves from our direct scrape feeds, keyed by book (tab, betfair, sportsbet, ladbrokes, neds, pointsbet, bluebet, palmerbet). Each book maps to an array of { timestamp, odds } points captured at ~5-minute intervals. Available for dates from late July 2026 onward; older dates return an empty bookFlucs.
GET /api/v1/racing/results
Historical race results with per-runner detail including jockey, trainer, margin, barrier, weight, winning time, finishing position and BSP.
GET /api/v1/racing/results?since=2026-08-01&race_type=T&limit=50
Params: since / until (YYYY-MM-DD), race_type (T/H/G), track_slug, track (substring), runner_slug, race_name (substring match), limit (Free: 50, API: 2000). Each runner: { name, tab_number, finish_position, jockey, trainer, margin, barrier, weight, win_bsp, place_bsp }. Race-level: { winning_time (seconds), mile_rate (seconds per mile) }.mile_rate is computed as (winning_time / distance_m) * 1609.344 when both fields are present.
GET /api/v1/racing/results/{date}
Complete resulted meetings for a date with per-runner finishing detail, pools and dividends.
GET /api/v1/racing/results/2026-08-03?venue=randwick
Params: date (path, YYYY-MM-DD), venue (optional). Each runner: { name, tab_number, finish_position, jockey, trainer, margin, barrier, weight, time, win_bsp }.
GET /api/v1/racing/futures
Ante-post and future race markets from PointsBet (outright Win boards) and Amused (future race listings). Returns runners with odds for upcoming feature races — Melbourne Cup, Cox Plate, Caulfield Cup, Golden Rose, international futures, plus harness and greyhound specials.
GET /api/v1/racing/futures?race_type=T&venue=menangle&limit=20
Params: race_type (T|H|G), venue (substring match), date (YYYY-MM-DD filter), limit (Cap: 50 free, 200 API). Each item: { date, venue, race_name, race_type, runners: [{ name, odds, bookmaker }], prize_money, bookmakers[] }. Data sourced from PointsBet futures (Win markets) and Amused future race listings, merged by date+venue.
GET /api/v1/tips
ML-driven game picks. Active (gameday) by default; pass include_settled=true to read historical settled tips for accuracy audits.
GET /api/v1/tips?sport_key=basketball_nba&min_confidence=3&limit=20
Params: sport_key, min_confidence (1–5), include_settled (boolean), limit (Free: 50, API: 200). Cache TTL 300 seconds.
{
"success": true,
"data": [
{
"id": "tip_abc",
"event_id": "...",
"sport_key": "basketball_nba",
"home_team": "Boston Celtics",
"away_team": "LA Lakers",
"commence_time": "...",
"pick": "Boston Celtics",
"pick_side": "home",
"confidence": 4,
"confidence_label": "Strong",
"consensus_prob_home": 0.62,
"consensus_prob_away": 0.38,
"predicted_margin": 7.5,
"predicted_margin_side": "home",
"resolution": "pending",
"actual_winner": null
}
]
}resolution is pending on active tips and win/loss/push (pick vs. result) once settled; actual_winner is null until settled, then home/away/draw. Both are only populated on include_settled=true rows.
GET /api/v1/resultsAPI plan
Final scores for completed games. winner is derived server-side as home, away, or draw. Historical archive — requires the paid API plan; free keys receive 402.
GET /api/v1/results?sport_key=basketball_nba&since=2026-05-01&limit=100
Params: sport_key, since (ISO 8601 date — filters commence_time ≥), limit (Free: 100, API: 500). Cache TTL 300 seconds.
GET /api/v1/injuries
Current injury status feed. Ordered most-recently-updated first.
GET /api/v1/injuries?sport_key=basketball_nba&team=lakers&limit=100
Params: sport_key, team (substring), limit (Free: 100, API: 500). Cache TTL 600 / 300 / 300 seconds.
{
"success": true,
"data": [
{
"id": "inj_abc",
"sport_key": "basketball_nba",
"player_name": "LeBron James",
"player_slug": "lebron-james",
"team": "Los Angeles Lakers",
"status": "day-to-day",
"reason": "ankle",
"date": "2026-05-17",
"season": "2025-26",
"source": "krok-odds",
"updated_at": "..."
}
]
}GET /api/v1/historical/player-game-logAPI plan
Per-player game log archive. Requires sport_key. Returns each player's recent_games[] sorted most-recent first. Substring filter on player or team applies in-memory after the indexed query.
GET /api/v1/historical/player-game-log?sport_key=basketball_nba&player=lebron&limit=50
Params: sport_key (required), player (substring), team (substring), season, limit (Free: 50, API: 200). Cache TTL 600 / 300 / 300 seconds.
GET /api/v1/historical/team-game-logAPI plan
Team-level game log archive. Requires sport_key. Returns final score, period splits, league, country, and status per game.
GET /api/v1/historical/team-game-log?sport_key=basketball_nba&team=lakers&limit=100
Params: sport_key (required), team (substring matches home OR away), since (ISO date), until (ISO date), limit (Free: 100, API: 500). Cache TTL 600 / 300 / 300 seconds.
GET /api/v1/gameday/h2h
Head-to-head record snapshot for upcoming fixtures. Returns aggregate summary (total meetings, home/away wins, draws, win %) plus last_meetings[] ordered most recent first.
GET /api/v1/gameday/h2h?sport_key=aussierules_afl&limit=50
Params: sport_key, home_team (substring), away_team (substring), event_id, limit (Free: 50, API: 200). Cache TTL 300 seconds.
GET /api/v1/gameday/best-prices
Top-of-book per market and selection for upcoming fixtures, with the offering bookmaker and how many books currently list that selection.
GET /api/v1/gameday/best-prices?sport_key=basketball_nba&market=h2h&limit=50
Params: sport_key, event_id, market (h2h|spreads|totals or player prop key), limit (Free: 50, API: 200). Cache TTL 300 seconds.
GET /api/v1/odds-historyAPI plan
Open/latest/movement summary per event, sourced from the permanent odds_history table (with full bookmaker arrays and opening odds), falling back to the gameday snapshot archive if no history exists. Each event includes opening_odds (the first bookmaker odds seen for this event) and bookmakers (the latest/closing bookmaker odds), plus the derived opens/latest/movement fields extracted from H2H prices. direction is one of drift, shorten, flat. Set include_snapshots=true to also return raw tick history when using the gameday fallback (much larger payload). Historical archive — requires the paid API plan; free keys receive 402.
GET /api/v1/odds-history?sport_key=basketball_nba&limit=25
Params: sport_key, event_id, market, selection (substring), include_snapshots (boolean), limit (Free: 25, API: 1000). Cache TTL 300 seconds.
GET /api/v1/steam-moves
Sharp money signal feed: outcomes where multiple AU books shifted at the same time. direction is shortening or drifting; move_pct is the signed % change. Most recent first, server caps at 250 to keep latency tight.
GET /api/v1/steam-moves?sport_key=basketball_nba&direction=shortening&min_move_pct=5&limit=50
Params: sport_key, event_id, direction (shortening|drifting), min_move_pct (number), limit (Free: 50, API: 200). Cache TTL 300 seconds.
/steam-moves — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport |
| event_id | string | — | Filter by event |
| direction | string | — | shortening or drifting |
| min_move_pct | number | — | Minimum move percentage |
| bookmaker | string | — | Filter by bookmaker |
| limit | integer | — | Max results (Free: 50, API: 200) |
GET /api/v1/tips/accuracy
Model track record. Returns wins / losses / pushes / decided / hit_rate rolled up per sport, with a by_confidence[] breakdown.
GET /api/v1/tips/accuracy?sport_key=basketball_nba
Params: sport_key (optional — omit to list all sports ordered by sample size), limit (Free: 50, API: 200). Cache TTL 600 / 300 / 300 seconds.
GET /api/v1/racing/results
Historical AU race results with BSPs. Each item has the winning runner plus the full sorted runners[] list (finish position, win/place results, jockey, trainer).
GET /api/v1/racing/results?race_type=T&track_slug=randwick&since=2026-04-01&limit=50
Params: race_type (T|H|G), track_slug, track (substring), runner_slug, since, until, limit (Cap: 500). Cache TTL 300 seconds.
GET /api/v1/teams/canonical
Canonical team registry — the lookup table behind slug-based filtering across the rest of the API. Slow-changing, aggressively cached.
GET /api/v1/teams/canonical?sport_key=basketball_nba&limit=100
Params: sport_key, slug, name (substring), limit (Free: 100, API: 500). Cache TTL 3600 / 1800 / 600 seconds.
GET /api/v1/sports
Returns all sports supported by the Krok Odds engine. Optional filter by category.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| apikey | string | Required. Your API key (or X-API-Key header) |
| category | string | Filter by category (e.g. Soccer, Cricket, Tennis) |
Example Response
{
"success": true,
"data": [
{
"key": "aussierules_afl",
"label": "AFL",
"category": "AU Sports",
"au_coverage": "high",
"refresh_interval_seconds": 60
}
],
"meta": { "total": 76, "timestamp": "..." }
}GET /api/v1/status
Public endpoint. No API key required. Returns sync engine health and last update time.
{
"status": "operational",
"sync": {
"healthy": true,
"last_sync_seconds_ago": 18,
"cycle_count": 4821,
"remaining_api_credits": 4821
},
"timestamp": "..."
}GET /api/v1/bookmakers
Machine-readable bookmaker coverage registry — every book + exchange + aggregator feed Krok ingests (licensed odds aggregators, betting-exchange and totalisator feeds, and more), with region and provider metadata. All tiers (rate-limited, no feature gate). Filter by region (au/us/uk/eu), provider, include_aggregators (true/false), and fields projection. Free: 100, API: 500.
Odds Feed — redistributable tier
Every other endpoint on this page serves odds we license from aggregators, which your agreement does not permit you to redistribute. The /api/v1/odds-feed/* family is different: it serves only odds KrokOdds scrapes directly from bookmakers, so it is the one tier you may resell, republish or embed in your own product. Responses carry X-Krok-Data-Source: direct-scrape and meta.redistributable: true. Aggregator data is never mixed in.
Direct-scrape books: Sportsbet, Ladbrokes, PointsBet, BlueBet, Palmerbet, TAB (racing + sports + futures + tote), TABtouch (RWWA racing — WA tote + fixed), Unibet (sports — Kambi scrape), Betr (sports), BetRight (sports), PuntersTech (sports — 20+ white-label brands), Generation Web (racing + sports — 24 white-label brands), Betfair Exchange, and prediction markets (Polymarket, Kalshi). Racing coverage spans all corporate/tote feeds including TABtouch; sports coverage includes Ladbrokes, TAB, Sportsbet, PointsBet, Betfair, Betr, BetRight, PuntersTech, Unibet, and Generation Web. Call /odds-feed/bookmakers for live-vs-pending status rather than assuming.
GET /api/v1/odds-feed/bookmakers
The bookmakers we scrape directly, with per-feed status (live or pending) and whether each supplies racing, sports or both. Registry read — no database hit. All tiers.
GET /api/v1/odds-feed/sports
Sports with live direct-scrape coverage, each with an exact event_count and the contributing bookmakers. Counts come from Firestore aggregates, not scans. Filter by bookmaker (same keys as /odds-feed/bookmakers) to see one book's coverage and its counts alone; meta.bookmaker_sports_feed tells you whether an empty result means the book is racing-only/pending rather than idle. All tiers. Cache 1800s.
GET /api/v1/odds-feed/sports/{sport}
Events + full market/selection odds for one sport, fanned out across every book that scrapes it and normalised onto a single shape (markets[].selections[] with price, line, place, suspended) — TAB's props[]/win shape is converted for you. {sport} is a canonical slug from /odds-feed/sports (e.g. aussie-rules, which spans TAB's “AFL Football” and Ladbrokes' “Australian Rules”). Filter by bookmaker, competition, upcoming=true; set markets=false for a fixtures-only payload. Free: 25, API: 1000. Cache 300s.
GET /api/v1/odds-feed/prediction-markets
Contract prices from Polymarket and Kalshi, de-vigged into implied probabilities and enriched with CLOB order-book data (liquidity, best bid/ask, spread, last trade, 24h change). Each row is matched to a KrokOdds event where possible. Filter by source (polymarket or kalshi), sport (KrokOdds sport key e.g. basketball_nba), and type (game or futures). Synced every 30 minutes. All tiers. Cache 600s.
GET /api/v1/odds-feed/racing
Meetings → races → runners → per-book fixed and tote odds, from our own scrapes across all six racing feeds. Defaults to today's Melbourne date; filter by date (YYYY-MM-DD), bookmaker, venue, race_type (R thoroughbred, H harness, G greyhound — T accepted as an alias for R). Meetings join across books on venue_slug. Free: 10, API: 500. Cache 300s.
Both list endpoints report meta.truncated and meta.scan_capped_bookmakers so you can tell a book's tail was cut from a book having no data.
GET /api/v1/odds-feed/racing/movements
Cross-bookmaker price movements for today's / tomorrow's races — each book's opening vs current price per runner, plus the aggregate best-price move. Computed from our own racing_odds_snapshots time series. All tiers. Cache 300s.
GET /api/v1/odds-feed/results
Settled race results — winner plus full finishing order — from our own result feeds (TAB finishing data, OddsPro cross-book results). Filter by date (YYYY-MM-DD, AU-local; defaults today), sport (R/H/G), source (tab/oddspro), venue (slug substring). Redistributable direct-scrape data. All tiers. Cache 300s.
GET /api/v1/odds-feed/results/{date}
All settled race results for a specific AU-local date, taken from the path (YYYY-MM-DD) instead of ?date=. Same source, shape and tier as /odds-feed/results; optional sport / source / venue filters still apply. All tiers. Cache 300s.
GET /api/v1/odds-feed/clv
Historical closing line data for value analysis — compare your prices against the sharpest market close, sourced from our own direct scrapes so it is redistributable. Filter by sport, bookmaker, from/to (YYYY-MM-DD date range on commence time). Free: 50, API: 500. Cache 300s.
curl "https://krokodds.com.au/api/v1/odds-feed/clv?sport=nba&from=2026-08-01&to=2026-08-07&limit=50"
GET /api/v1/odds-feed/racing/historyAPI plan
Historical per-book, per-runner racing odds snapshots at ~5-min granularity, from the BigQuery cold archive — the resale / backtest feed of our own direct scrapes, so it is redistributable. from and to (YYYY-MM-DD) are required and the window is capped, so every query is partition-pruned; an unbounded scan returns 400. Filter also by venue, bookmaker, race_type. Bulk archive — requires the paid API plan; free keys receive 402. Cache 1800s.
{
"success": true,
"data": [
{
"event_id": "00271fc9-3bbc-4db2-ab18-ec7c97436dda",
"bookmaker": "Ladbrokes",
"bookmaker_key": "ladbrokes",
"sport": "Australian Rules",
"sport_slug": "aussie-rules",
"competition": "AFL",
"event": "Essendon vs GWS Giants",
"home": "Essendon",
"away": "GWS Giants",
"start_time": "2026-07-19T06:40:00Z",
"in_play": false,
"market_count": 255,
"markets": [
{
"key": "h2h",
"name": "Match Betting",
"selections": [
{ "name": "Essendon", "price": 6.5, "line": null, "place": null, "suspended": false },
{ "name": "GWS Giants", "price": 1.11, "line": null, "place": null, "suspended": false }
]
}
],
"captured_at": "2026-07-19T00:45:02.148Z"
}
],
"meta": {
"count": 1,
"sport": "aussie-rules",
"total_matched": 67,
"truncated": true,
"scan_capped_bookmakers": [],
"redistributable": true,
"license": "krokodds-direct-scrape"
}
}GET /api/v1/gameday/props
Pre-computed player-prop snapshots used by the gameday board. One row per event with props denormalised inside. Filter by sport_key, event_id, market, or player_slug. Free: 50, API: 200. Cache 300s.
GET /api/v1/gameday/summaries
Editorial summaries (headline + storylines + best price snapshot) keyed by event. Filter by sport_key or event_id. Free: 50, API: 200. Cache 600/300/300s.
GET /api/v1/gameday/alt-lines
Alternative-line ladders for spread + total markets. best_by_line keyed {market}|{line}. Free: 50, API: 200. Cache 300s.
GET /api/v1/extended-markets
Net-new derivative markets sourced beyond the primary odds feed — half / period / inning splits, soccer corners + cards, NHL per-period lines, MLB inning lines + total hits, AFL / NRL team-totals + tries, alt-totals. Mirrors the v4 bookmakers → markets → outcomes shape. Filter by sport_key, event_id, market (substring match on market key). Free: 50, API: 200. Cache 300s.
GET /api/v1/gameday/live
In-play score + status snapshot. Filter by status (pre/live/final). Cache 300s. Free: 50, API: 200.
GET /api/v1/gameday/event/{id}
Bulk endpoint. One call replaces seven — fans out across summary, h2h, best_prices, alt_lines, props, odds_history, live in parallel. Failed parts return null; never 5xx the whole bundle. sport_key required when parts includes h2h or live. Use parts=summary,best_prices to slim payloads. Cache 300s.
GET /api/v1/player-props-stats
Per-player prop hit rates. Long-run hit/miss/push counters for player-prop lines. Filter by sport_key, player_slug, player_canonical, market_key, side (over/under). hit_rate is 0–1, 4dp. Use player_slug for individual player analysis. Free: 50, API: 200. Cache 600/300/300s.
/player-props-stats — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport |
| player_slug | string | — | Filter by player slug |
| player_canonical | string | — | Filter by canonical name |
| market_key | string | — | Filter by market |
| side | string | — | over or under |
| limit | integer | — | Max results (Free: 50, API: 200) |
GET /api/v1/player-props-results
Per-event resolved player-prop outcomes. outcomes[] is denormalised inside the doc; filter by player_name (substring) or market. event_id does a direct doc fetch (id slug-safe, /→_, ≤1500ch). Free: 50, API: 200. Cache 600/300/300s.
/player-props-results — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sport_key | string | — | Filter by sport |
| event_id | string | — | Filter by event |
| player_name | string | — | Filter by player name (substring) |
| market | string | — | Filter by market type |
| limit | integer | — | Max results (Free: 50, API: 200) |
GET /api/v1/racing/runner-form
Per-runner historical race form (sub-collection runner_historical_stats/{sport}__{slug}/recent_races). runner_slug required. Sport optional — when omitted, scans all three (racing_T/racing_H/racing_G). Cap 500. Cache 300s. Each entry includes class_conditions — the race class text (e.g. "BM58", "Maiden", "3-4YO BM68") for that start.
GET /api/v1/racing/ratings
Model ratings for one race (racing_ai_picks + Betfair money flow). race_id required; optional meeting_id must match or 404. Money flow fields null when Betfair tips doc not available (outside ±36h window). Cache 600 / 300 / 300s.
GET /api/v1/racing/ratings?race_id=flemington_2026-03-01_r4
Params: race_id (required), meeting_id (optional, must match race_id prefix).
| Field | Type | Description |
|---|---|---|
| model | string | Model name used for rating generation (e.g. krok_v3). |
| ratings_version | string | Version tag for the ratings pipeline. |
| race_id | string | Race identifier. |
| meeting_id | string | Parent meeting identifier. |
| top_pick | object | Runner object of the top-rated runner. |
| score | number | Composite confidence score for the top pick. |
| tier | string | Rating tier (e.g. strong, moderate, marginal). |
| breakdown | object | Per-component score breakdown. Sub-fields: career, track, distance, form, valueGap, freshness, classFit, weightEdge, barrier, connections — each a numeric score. |
| top_analysis | string | Narrative analysis of the top pick. |
| field_analysis | string | Narrative analysis of the full field. |
| risk | string | Risk assessment for the top pick. |
| track_condition | string | null | Track condition at time of race. |
| weather | string | null | Weather at time of race. |
| value_picks | array | Array of value-rated runners. |
| market_mover | object | null | Biggest market mover in the field. |
| pick_rationale | string | null | One-liner AI rationale for why this runner was selected. |
| result | string | null | Settlement result: win, place, loss, pending. |
| winning_slug | string | null | Slug of the winning runner. |
| race_name | string | Name of the race. |
| race_number | number | Race number. |
| venue | string | Venue name. |
| state | string | null | State code. |
| race_type | string | T/H/G. |
| jump_time | string | Scheduled jump time. |
| date | string | Race date. |
| confidence | string | High or low confidence rating. |
| runners | array | Per-runner rating details (see below). |
Per-runner fields
| Field | Type | Description |
|---|---|---|
| win_prob | number | Model win probability (0-1). |
| fair_odds | number | Fair decimal odds (1/win_prob). |
| confidence | number | Per-runner confidence score. |
| rank | number | Runner rank in the field (1 = top pick). |
| edge_pct | number | Edge percentage over the market price. |
| value | number | Value rating score. |
| money_share | number | Betfair money share (0-1). |
| money_delta | number | Betfair money flow delta. |
| rating | number | Composite model rating. |
GET /api/v1/racing/runner-stats
Career record plus computed splits per runner. runner_slug required. sport_key optional — when omitted, probes racing_T/racing_H/racing_G and returns the first with a career record. Returns historical (name, starts/wins/places/win_rate/place_rate/avg_win_bsp, last_track, last_date) and splits (by_track, by_distance, by_going, by_track_distance, by_prep_stage (first_up/second_up/in_prep, each a starts/wins/places/win_rate/place_rate/avg_bsp split), class_change (counts of up/down/same/new_count class moves across the analysed form; runs whose class is unreadable are counted in none), avg_days_between_starts, spell_length, form_string, best_bsp, best_bsp_label, total_analysed). Cache 600 / 300 / 300s.
GET /api/v1/racing/connections
Jockey / trainer win strike rates. names required — comma-separated, max 50. type = jockey | trainer | both (default both). Names resolve to slugs; form is keyed off the TAB spelling, which abbreviates the first name, so a full name (Damian Lane) also falls back to the initial form (d-lane) — matched_slug reports which doc answered. Unknown names return empty.
GET /api/v1/racing/connections?names=d-lane,j-mcneil&type=both
Params: names (comma-separated, required), type (jockey | trainer | both), limit (Free: 50, API: 200).
| Field | Type | Description |
|---|---|---|
| slug | string | Matched TAB slug for this connection. |
| matched_slug | string | Which slug variant answered (full name or abbreviated form). |
| name | string | Display name. |
| type | string | jockey or trainer. |
| starts | number | Total career starts (as jockey or trainer). |
| wins | number | Total career wins. |
| win_pct | number | Win percentage (0–100). |
| place_pct | number | Place percentage (0–100). |
| roi | number | Return on investment % (flat win). |
| recent_form | array | Last 10 results: W/P/L. |
| track_stats | array | Per-venue breakdown: array of {venue, starts, wins, places, win_pct} — shows strike rate at each track. |
| racing_com_profile | object | null | Racing.com profile data when available: {season_form, overall_ranking, season_ranking, total_wins, total_runners, win_rate}. null when no profile exists. |
GET /api/v1/racing/connections/season-stats
Season-by-season performance statistics for jockeys and trainers. Shows wins, places, strike rates and ROI broken down by racing season.
GET /api/v1/racing/connections/season-stats?name=d-lane&type=jockey&limit=5
Params: name (required, single name), type (jockey | trainer), limit (number of seasons, default 5). Each season: { season, starts, wins, places, win_pct, roi }. Sorted by season descending (most recent first).
GET /api/v1/racing/connections/combinations
Jockey/trainer, jockey/horse, and trainer/horse combination statistics from historical results. Returns win strike rate, runs, and wins per pair over the last 90 days.
GET /api/v1/racing/connections/combinations?type=jockey_trainer&names=jockey-name,trainer-name&limit=20
Params: type (jockey_trainer | jockey_horse | trainer_horse, default jockey_trainer), names (comma-separated, optional filter), limit (Free: 50, API: 200). Each pair: { primary, secondary, runs, wins, win_strike_rate }. Sorted by wins descending. Data window: 90 days.
GET /api/v1/sport-activity
Per-sport "is this active right now" flag with has_outrights. Filter by sport_key, group, or active=true. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/ev-hit-rates
Roll-up CLV / EV / hit-rate stats per opportunity category (arb, ev, middles, low_holds, player_props). Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/opportunity-historyAPI plan
Read-side archive of expired opportunities. type filter (arb/ev), sport_key, since. Records cleaned up after 24h — backtest only. Historical archive — requires the paid API plan; free keys receive 402. Free: 50, API: 200. Cache 300s.
GET /api/v1/closing-lines
Closing-line snapshots for settled events — the consensus price at market close, for CLV backtesting. Sourced from the permanent odds_history table when available, falling back to gameday snapshots. Each event now includes opening_odds (first bookmaker odds) alongside the closing close prices, so consumers can compute CLV directly without a separate API call. Filter by sport_key, event_id (direct doc fetch), or since. Free: 50, API: 250. Cache 600/300/300s.
GET /api/v1/clv-archive/{eventId}
The full archived closing-odds snapshot for one event — per-book bookmakers[] with their markets / outcomes, the price frozen at market close. Direct doc fetch by eventId (path segment). Returns event_id, sport, sport_title, home_team, away_team, commence_time, bookmakers, and archived_at. Backs retroactive CLV on manually logged bets; also useful for CLV backtesting and debugging a single event. Requires a logged-in session (not an API-key tier) — 401 if unauthenticated, 404 if no archive exists for that event.
GET /api/v1/weather
Per-event venue weather: temp, wind speed/direction, precipitation, conditions. Filter by event_id or sport_key. Outdoor sports only (NFL/AFL/MLB/soccer/racing); indoor returns null. Free: 50, API: 200. Cache 1800/600/300s.
GET /api/v1/stream/opportunities
Real-time Server-Sent Events stream of value opportunities — arbitrage, positive EV, middles and low holds — pushed as they appear, no polling required. Requires a plain HTTP GET with an SSE-capable client (Accept: text/event-stream, e.g. EventSource or curl -N); each frame is a ready/snapshot/delta event with a JSON data: payload. Connection is held open (capped at 10 min; reconnect after). Free tier.
/stream/opportunities — query filters
| Parameter | Type | Default | Description |
|---|---|---|---|
| types | string | — | Comma-separated filter: arbs, snipes, middles, low_holds (default: all four) |
| sport_key | string | — | Filter by sport |
| min_value | number | — | Minimum opportunity value (ignored for low_holds) |
curl -N "https://krokodds.com.au/api/v1/stream/opportunities" -H "X-API-Key: ***"
GET /api/v1/leaderboards/soccer
Soccer top-scorers / top-assists tables. kind (topscorers/topassists), league_id, season all required. Returns a single object with players[] truncated by limit. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/mma/fights
Upcoming + completed MMA fight cards (UFC, Bellator, PFL). Filter by fight_id or since. Free: 50, API: 200. Cache 1800/600/300s.
GET /api/v1/f1/races
F1 race calendar with weather + circuit metadata. Filter by race_id, season, since. Free: 50, API: 200. Cache 1800/600/300s.
GET /api/v1/historical/player-statsAPI plan
Full player historical profiles: season averages, splits, coverage windows, market lines. sport_key required; slug (single player) and team (in-memory filter) optional. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/historical/aflAPI plan
AFL archive. kind=player (player game logs) or kind=match (results). Optional year; round (player only, in-memory). Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/historical/nrlAPI plan
NRL player and match data. Defaults to current (2024+). Pass kind=player or kind=match for the historical archive (2010-2023). Optional season (e.g. 2025). Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/historical/shot-chartAPI plan
NBA shot charts — every field-goal attempt for a player-season with half-court (locX, locY) coordinates, made/missed flags and per-zone FG% splits. slug (canonical player slug, e.g. nikola_jokic) required; optional season (e.g. 2025-26). Free: 20, API: 60. Cache 3600/1800s.
GET /api/v1/soccer/closing-odds
Soccer match results with opening + closing odds across 6 leagues — Bet365 & Pinnacle 1X2, Asian handicap and Over/Under 2.5 closing prices (the CLV reference set). league (E0/E1/SP1/D1/I1/F1; league_code alias) and/or season (string, e.g. 2021-2022), optional from/to date range (YYYY-MM-DD). Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/soccer/bundesligaAPI plan
German-football results — a fallback settlement source for Bundesliga props. league (bl1/bl2/dfb, required), optional season (start year, e.g. 2024) and matchday. Returns goals, half-time scores, matchday and venue. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/advanced-stats
Multiplexed endpoint providing sport-specific advanced metrics across 14 datasets via a single source parameter — one integration instead of fourteen. source is required; season is an optional equality filter on most sources (some map it to year — see below), plus per-source in-memory filters. Free: 100, API: 500. Cache 3600/1800/600s.
| source | Extra filters | Description |
|---|---|---|
| mlb_advanced | team, playerType | MLB batted-ball metrics (exit velocity, barrel rate, expected outcomes). |
| nhl_skaters | — | NHL skater advanced metrics. |
| ncaab_schools | — | College basketball team advanced stats. |
| soccer_xg | — | Soccer expected goals (xG) by player. |
| ncaaf_player_games | — | College football player game logs. |
| nfl_ngs | — | NFL Next Gen Stats tracking data. |
| nfl_snaps | — | NFL snap count data. |
| nfl_depth | — | NFL depth charts. |
| soccer_fbref | league, compId, sportKey, squad | Soccer player season stats (xG/npxG/xA + progressive carries). |
| nrl_player_games | round, teamNickname, playerSlug | NRL player game logs. |
| afl_matches | season→year, team1, team2, venue | AFL match data. |
| tennis_closing_odds | season→year, tour, surface, round | Tennis match closing odds. |
| nhl_moneypuck_skaters | team, position, playerSlug | NHL skater analytics (expected goals, Corsi, etc.). |
| nhl_moneypuck_goalies | team, playerSlug | NHL goalie analytics (expected goals saved, etc.). |
soccer_fbref attribution: “Data Provided by Sports Reference, LLC” (required by source license).
Player pages additionally surface Wave-3 derived views (not separate source values): NHL individual scoring chances / high-danger from play-by-play, soccer per-90 passing/possession/defense, college football team efficiency (down splits / red-zone / 3rd-down), derived AFL player ratings, and NRL advanced running/defensive metrics.
curl "https://krokodds.com.au/api/v1/advanced-stats?source=mlb_advanced&season=2026&limit=20"
GET /api/v1/cricket/innings
Ball-by-ball derived player innings (batting + bowling). sport_key, match_type (T20/ODI/Test), or season (string) — at least one required. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/tennis/matches
ATP + WTA singles results. season (number); tour + surface narrow in-memory. Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/f1/results
F1 driver race results (distinct from /f1/races schedule). season (number) + round (in-memory). Free: 100, API: 500. Cache 3600/1800/600s.
GET /api/v1/golf/statsAPI plan
Player strokes-gained and scoring projections. No filters — full field per pull. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/golf/rankingsAPI plan
World golf rankings snapshot. Optional player filter. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/golf/skillsAPI plan
Player skill breakdowns — off-the-tee, approach, short game, putting. source = skills (default) or approach (approach-shot distance bands); optional player. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/cycling/resultsAPI plan
Race results and general-classification standings. Optional race filter. Free: 20, API: 50. Cache 3600/1800s.
GET /api/v1/cycling/ridersAPI plan
Rider profiles — team, nationality, specialty. Optional name / team filters. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/cycling/startlistsAPI plan
Confirmed race startlists. Optional race / date (YYYY-MM-DD) filters. Free: 20, API: 50. Cache 3600/1800s.
GET /api/v1/esports/matchesAPI plan
Live + upcoming esports matches (League of Legends, CS2, Dota 2). Filter by sportKey / status. Free: 50, API: 200. Cache 900/300s.
GET /api/v1/esports/teamsAPI plan
Team rosters and metadata. Optional sportKey filter. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/esports/leaguesAPI plan
League and tournament metadata. Optional sportKey filter. Free: 50, API: 200. Cache 3600/1800s.
GET /api/v1/exchange
Multiplexed exchange pricing data across 5 sources via a single source parameter — source is required, plus per-source filters below. Free: 100, API: 500. Cache 600/300/300s.
| source | Extra filters | Description |
|---|---|---|
| bsp | raceKey, venueSlug, marketType | Settled exchange starting prices — the sharpest closing price for racing. |
| results | raceKey | Race results with finishing data. |
| match_odds | sport (required) + eventId | Match odds with implied probabilities across sports. |
| scorer_props | sport (required) + eventId, marketType | Player scorer market odds (first goal, anytime scorer, etc.). |
| snapshots | sport (required) + eventId | Live pre-race price snapshots. |
curl "https://krokodds.com.au/api/v1/exchange?source=bsp&limit=20"
GET /api/v1/bulkAPI plan
Cursor-paginated whole-collection dumps of the historical archive. Omit dataset for the manifest; then pass dataset (e.g. team_game_logs, player_history, mlb_advanced, exchange_bsp) and walk pages via next_cursor until it is null. Optional sport_key (e.g. rugbyleague_nrl) filters player_game_logs and nrl_player_games to a single sport. For sport-filtered player game logs, prefer /v1/historical/player-game-log which supports sport_key natively. Free: 100, API: 500 rows per page. Cache 1800s.
GET /api/v1/bulk?dataset=player_history&limit=5000 GET /api/v1/bulk?dataset=player_history&cursor=<next_cursor>&limit=5000 GET /api/v1/bulk?dataset=nrl_player_games&sport_key=rugbyleague_nrl&limit=5000
GET /api/v1/exportAPI plan
Spreadsheet-ready CSV download of a BigQuery archive dataset. Pass dataset (one of game_results, player_props_results, model_track_record, gameday_odds_history, clv_archive, ev_hit_rates) and an optional limit (cap 5000). Nested fields are JSON-encoded per cell; the response is text/csv as a file attachment. Add format=json for the standard JSON envelope instead.
GET /api/v1/export?dataset=game_results&limit=5000 GET /api/v1/export?dataset=model_track_record&format=json
GET /api/v1/reference/headshots
Static player headshot URLs (all tiers). sport_key required; slug optional (single player). Returns name/slug/photo_url/source. Free: 200, API: 1000. Cache 86400/43200/21600s.
GET /api/v1/reference/team-logos
Static team logo URLs + name aliases (all tiers). sport_key required. Returns names/logo/external_id/source. Free: 200, API: 1000. Cache 86400/43200/21600s.
GET /api/v1/reference/players
Comprehensive player profile data — bio, physical attributes, career info. Filter by name / sport. Free: 50, API: 200. Cache 86400/43200s.
GET /api/v1/reference/venues
Detailed venue information — location, capacity, surface type. Filter by name / sport. Free: 50, API: 200. Cache 86400/43200s.
GET /api/v1/predictions
api-sports prematch predictions cache. Single-doc mode (fixture_id) or list mode (sport_key, league_id, season, since filters). Soccer only at present. Fields: advice, winner, percent home/draw/away, under_over, goals avg, h2h_count. ai_overlay object adds Krok's AI-on-math layer: math_pick, ai_pick, final_pick, ai_confidence, alpha, ai_evidence, ai_agreed/ai_override, settler result. Math wins outright when top% ≥ 75; AI may override only with ≥ 0.5 confidence + ≥ 2 evidence tags + chosen side ≥ 22%. null until daily AI pass runs. Free: 100, API: 500. Cache 1800/600/300s.
GET /api/v1/me
Introspection endpoint. Returns the calling key's tier, monthly credit pool, sliding-window state, and a masked key preview. Never cached (Cache-Control: private, no-store) and never 429s — informational only.
{
"success": true,
"data": {
"tier": "api",
"monthly_limit": 10000,
"current_usage": 1283,
"remaining": 8717,
"usage_pct": 12.83,
"reset_date": "2026-06-01",
"per_request_limit": 500,
"rate_limit_window": { "limit": 300, "remaining": 298, "reset": "2026-05-18T09:01:00.000Z" },
"api_key_preview": "krok...a4f9"
}
}Webhooks
Receive real-time HTTP POST notifications when new opportunities are detected. Available on all tiers.
Register a webhook
POST /api/v1/webhooks
Authorization: session cookie (logged in)
{
"url": "https://your-server.com/hook",
"events": ["arb", "ev", "middle"],
"minValue": 2.0
}Payload format
{
"event": "arb",
"timestamp": "2026-03-01T10:00:00Z",
"data": {
"id": "...",
"event": "Brisbane Lions v Melbourne Demons",
"sport": "aussierules_afl",
"value": 2.4,
"bookmaker1": "Sportsbet",
"bookmaker2": "TAB",
"odds1": 2.10,
"odds2": 2.05
}
}Verifying signatures
// Node.js
const sig = req.headers['x-krok-signature'] // "sha256=abc123..."
const expected = 'sha256=' + createHmac('sha256', YOUR_SECRET)
.update(rawBody).digest('hex')
if (sig !== expected) throw new Error('Invalid signature')
Response Objects
Arbitrage object type=arbs
Two bookmakers have diverging prices on the same event. Combined implied probability <100% = guaranteed profit. The value field is the ROI % on your total stake.
{
"success": true,
"data": {
"arbs": [
{
"id": "nrl_bulldogs_vs_broncos_tab_sportsbet",
"event": "Bulldogs vs Broncos",
"home_team": "Bulldogs",
"away_team": "Broncos",
"sport": "NRL",
"sport_key": "rugbyleague_nrl",
"market": "h2h",
"line": null,
"selection1": "Bulldogs",
"selection2": "Broncos",
"bookmaker1": "TAB",
"bookmaker2": "Sportsbet",
"odds1": 2.45,
"odds2": 1.80,
"value": 3.21,
"tool_type": "surebet",
"status": "upcoming",
"commence_time": "2026-03-02T10:30:00Z",
"updated_at": "2026-03-01T04:00:12Z",
"instructions": "Place $44.90 on Bulldogs @ TAB and $55.10 on Broncos @ Sportsbet"
}
]
},
"meta": {
"tier": "api",
"limit": 500,
"requested_limit": 20,
"timestamp": "2026-03-01T04:00:15.234Z"
}
}| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier for this opportunity. |
| event | string | Human-readable event name, format: "Home vs Away". |
| home_team | string | null | Home team parsed from event string. null if event format unexpected. |
| away_team | string | null | Away team parsed from event string. null if event format unexpected. |
| sport | string | Sport title, e.g. NRL, AFL, NBA. |
| sport_key | string | Sport key, e.g. rugbyleague_nrl. |
| market | string | Market type: h2h (moneyline), spreads, totals, or player prop key. |
| line | number | null | Spread/total line for spreads/totals/props markets. null for h2h. |
| selection1 | string | First outcome name, e.g. Bulldogs. |
| selection2 | string | Second outcome name, e.g. Broncos. |
| bookmaker1 | string | Bookmaker offering selection1 odds. |
| bookmaker2 | string | Bookmaker offering selection2 odds. |
| odds1 | number | Decimal odds for selection1. |
| odds2 | number | Decimal odds for selection2. |
| value | number | ROI % on total stake. e.g. 3.21 = 3.21% guaranteed profit. |
| tool_type | string | Always surebet for arbs. |
| status | string | upcoming · live · finished |
| commence_time | ISO 8601 | Event start time in UTC. |
| instructions | string | Plain English stake split, e.g. Bet $44.90 @ TAB and $55.10 @ Sportsbet. |
| updated_at | ISO 8601 | When this opportunity was last recalculated. |
EV Snap object type=snipes
One bookmaker is offering better-than-fair odds on a selection. Fair odds are derived from the sharp exchange back/lay benchmark (or market average if no exchange line is available). The value field is the EV % — how much you expect to return per $100 wagered, long-term.
{
"success": true,
"data": {
"snipes": [
{
"id": "afl_richmond_vs_geelong_sportsbet_geelong",
"event": "Richmond vs Geelong",
"home_team": "Richmond",
"away_team": "Geelong",
"sport": "AFL",
"sport_key": "aussierules_afl",
"market": "h2hev",
"line": null,
"selection1": "Geelong",
"bookmaker1": "Sportsbet",
"bookmaker2": "Exchange Fair",
"odds1": 2.10,
"odds2": 1.90,
"value": 4.72,
"confidence": "high",
"sharp_price": 1.90,
"tool_type": "positive_ev",
"status": "upcoming",
"commence_time": "2026-03-05T06:40:00Z",
"updated_at": "2026-03-01T04:00:12Z",
"instructions": "Bet $100 on Geelong @ Sportsbet (2.10). Fair price 1.90 → +4.72% EV."
}
]
},
"meta": {
"tier": "api",
"limit": 500,
"timestamp": "2026-03-01T04:00:15.234Z"
}
}| Field | Type | Description |
|---|---|---|
| value | number | EV %. e.g. 4.72 = you expect +$4.72 per $100 bet over the long run. |
| sharp_price | number | The fair odds (no-vig exchange price or market average). This is your benchmark. |
| confidence | string | high = exchange-derived benchmark. lower = market average (less reliable). |
| home_team | string | null | Home team parsed from event string. |
| away_team | string | null | Away team parsed from event string. |
| line | number | null | Spread/total line for spreads/totals/props markets. null for h2h. |
| bookmaker2 | string | The sharp benchmark source: Exchange Fair or Market Avg. |
| market | string | h2hev for moneyline EV, or a player prop key e.g. playerpoints. |
| instructions | string | Plain English stake suggestion + fair-price benchmark. |
Racing meeting object /api/v1/racing/meetings
Full meeting + race + runner schema with BOM weather observation and 7-day forecast layered onto each meeting. Use races[].runners[].odds[] for the per-bookmaker price grid and best_win for the AU top of book.
{
"success": true,
"data": [
{
"id": "flemington_2026-03-01",
"venue": "Flemington",
"state": "VIC",
"tote_jurisdiction": "VIC",
"type": "T",
"date": "2026-03-01",
"race_count": 9,
"next_jump": "2026-03-01T05:10:00Z",
"weather": {
"summary": "Partly cloudy",
"temp_c": 22.4,
"rain_24h_mm": 0.2,
"wind_kmh": 14,
"wind_dir": "SSW",
"station": "Melbourne Airport",
"observed_at": "2026-03-01T04:30:00Z"
},
"weather_forecast": {
"date": "2026-03-01",
"min_c": 14,
"max_c": 26,
"precis": "Mostly sunny.",
"rain_chance_pct": 10,
"rain_range_mm": "0",
"state": "VIC"
},
"track_hint": "Good 4",
"rail_position": "True 3m",
"exotic_pools": {
"trifecta": 42000,
"first4": 28000,
"quadrella": 185000
},
"weather_updated_at": "2026-03-01T04:30:00Z",
"races": [
{
"id": "flemington_2026-03-01_r4",
"number": 4,
"jump_time": "2026-03-01T05:10:00Z",
"name": "TAB Handicap",
"distance": 1400,
"race_class": "BM78",
"status": "open",
"field_hold_pct": 104.2,
"runner_count": 12,
"prize_money": "$120,000",
"track_condition": "Good 4",
"start_type": null,
"pools": {
"win": 18500,
"place": 12000,
"exacta": 8500
},
"replay_video": "https://example.com/replay/r4.mp4",
"runners": [
{
"id": "r7",
"number": 7,
"name": "Gatwick",
"barrier": 3,
"jockey": "J. McNeil",
"trainer": "C. Maher",
"weight": 57.5,
"actual_weight": 57.5,
"claim": 1.5,
"silk_url": "https://example.com/silks/gatwick.png",
"pace_band": "on-pace",
"early_speed_rating": 82,
"dfs_form_rating": 68.5,
"form": "1-2-4",
"is_scratched": false,
"best_win": 6.50,
"best_win_bookmaker": "Sportsbet",
"implied_prob": 0.154,
"fixed_win": 6.50,
"fixed_place": 2.20,
"fixed_win_open": 8.00,
"fixed_pct_change": -18.75,
"flucs": [
{ "win": 8.00, "t": "2026-03-01T01:00:00Z" },
{ "win": 7.00, "t": "2026-03-01T03:30:00Z" },
{ "win": 6.50, "t": "2026-03-01T04:55:00Z" }
],
"tote_win": 7.20,
"tote_place": 2.40,
"tote_exact2": null,
"fav_win": false,
"fav_place": false,
"finishing_position": null,
"last_20_starts": 14,
"odds": [
{ "bookmaker": "Sportsbet", "win": 6.50, "place": 2.20 },
{ "bookmaker": "Ladbrokes", "win": 6.00, "place": 2.10 }
]
}
]
}
]
}
],
"meta": {
"count": 1,
"tier": "api",
"limit": 200,
"requested_limit": 50,
"timestamp": "2026-03-01T05:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
| id | string | Meeting id, typically venue_date. |
| venue | string | Race venue, e.g. Flemington. |
| state | string | AU state code, e.g. VIC. |
| tote_jurisdiction | string | null | TAB tote jurisdiction the pools/dividends were priced under (VIC/NSW/QLD/SA/WA/TAS/ACT/NT); null when no TAB card is joined. |
| type | string | T = Thoroughbred, H = Harness, G = Greyhounds. |
| date | string | Meeting date YYYY-MM-DD. |
| race_count | number | Number of races on the card. |
| next_jump | ISO 8601 | null | Earliest future race jump time across the card. |
| weather | object | null | Latest BOM observation: summary, temp_c, rain_24h_mm, wind_kmh, wind_dir, station, observed_at. |
| weather_forecast | object | null | BOM 7-day forecast for the meeting date: min_c, max_c, precis, rain_chance_pct, rain_range_mm, state. |
| track_hint | string | null | Track condition hint (e.g. Good 4, Soft 6) when available. |
| rail_position | string | null | Rail position (e.g. True 3m, Out 8m) when available. |
| exotic_pools | object | null | Meeting-level exotic pool totals: trifecta, first4, quadrella (dollar amounts). |
| barrier_bias | array | null | Historical barrier-draw bias for the venue & race type: array of {barrierNumber, totalStarts, wins, places, winRate, placeRate, advantage} over thousands of races. null when un-cached. |
| weather_updated_at | ISO 8601 | null | When weather payload was last refreshed. |
| races[] | array | Race cards. Each entry has id, number, jump_time, name, distance, race_class, status, field_hold_pct, runner_count, prize_money, track_condition, start_type (harness only: 'standing_start' for trot races, 'mobile' for pace races, null for thoroughbred/greyhound), pools (win/place/exacta dollar amounts), replay_video (URL to race replay), runners[]. |
| races[].runners[] | array | Runners. Each: id, number, name, horse_code (horse ID — use with /v1/racing/sectionals/{horseCode}), barrier, jockey, trainer, weight, actual_weight (declared weight in kg), claim (apprentice claim in kg, null when none), silk_url (URL to jockey silk image), pace_band (leader/on-pace/midfield/backmarker — measured early speed; null when the TAB speed map is unavailable), early_speed_rating (TAB early speed rating), dfs_form_rating (DFS form rating), form, is_scratched, best_win, best_win_bookmaker, implied_prob, fixed_win (current TAB fixed win odds), fixed_place (current TAB fixed place odds), fixed_win_open (opening TAB fixed win odds), fixed_pct_change (% change from open to current fixed win odds), flucs (array of {win, t} — fixed odds fluctuation history), tote_win (TAB tote win odds), tote_place (TAB tote place odds), tote_exact2 (TAB tote exacta odds, null if unavailable), fav_win (boolean — TAB favourite to win), fav_place (boolean — TAB favourite to place), finishing_position (1-based placing for resulted races, null otherwise), last_20_starts (number of starts in last 20 races), running_style (projected run style — leader/on-pace/midfield/backmarker from the daily form feed; null when un-rated), settling_position (projected in-run position; null when un-rated), class_profile ({current_rating, peak_rating, highest_class_won, optimal_range_min, optimal_range_max, trend} — runner's class rating profile; null when un-rated), class_fit ({race_class_rating, class_difference, within_optimal_range, assessment} — runner-vs-race class fit; null when un-rated), form_indicators (array of {label, category, sentiment, description} — positive/negative form signals; omitted when none), jockey_win_rate (jockey career win rate 0-1; null when un-cached), jockey_track_win_rate (jockey win rate at this track 0-1; null when the sample is thin), trainer_win_rate (trainer career win rate 0-1), trainer_track_win_rate (trainer win rate at this track 0-1), career_prize_money (runner career prize money; null when un-cached), sire, dam (runner pedigree; null when un-cached), runner_id (stable horse ID from FormFav — use for cross-meeting joins across meetings), prize_money_won (per-runner prize money from results, null when unsettled), odds[] (bookmaker/win/place). |
GET /api/stats/global
Live counts of all active opportunities in the system. Requires an active session (dashboard users only — not accessible via API key). Cached with 30-second stale-while-revalidate.
GET https://krokodds.com.au/api/stats/global
{
"totalCount": 847,
"arbCount": 124,
"snipeCount": 590,
"middleCount": 133,
"totalEv": 3.81,
"updatedAt": "2026-03-01T04:00:12.000Z"
}Health & Status
GET /api/health
Returns server health. Use for uptime monitoring. No auth required.
{
"status": "healthy",
"timestamp": "2026-03-01T04:00:15.234Z",
"uptime": 86400.3,
"version": "1.0.0",
"environment": "production",
"checks": { "server": "ok" }
}GET /api/ready
Returns readiness check including Firestore connectivity. Returns 503 if not ready.
{
"ready": true,
"timestamp": "2026-03-01T04:00:15.234Z",
"checks": {
"firestore": "ok",
"environment": "ok"
}
}Supported Sports
Use the sport_key in the sport filter parameter. The sport_key is returned in every response object for use in your own filtering.
Krok Odds monitors 156 sports — live and upcoming markets refresh every few minutes. Futures/outrights and preseason markets refresh every ~10 minutes.
AU Sports
aussierules_aflrugbyleague_nrlcricket_big_bashsoccer_australia_aleaguerugbyleague_nrl_state_of_originbasketball_nblrugbyunion_super_rugbyAmerican Football
americanfootball_nflamericanfootball_ncaafamericanfootball_cflamericanfootball_uflamericanfootball_nfl_preseasonamericanfootball_nfl_super_bowl_winneramericanfootball_ncaaf_championship_winnerBasketball
basketball_nbabasketball_ncaabbasketball_euroleaguebasketball_wnbabasketball_nba_preseasonbasketball_nba_championship_winnerBaseball
baseball_mlbbaseball_mlb_preseasonbaseball_kbobaseball_npbbaseball_ncaabaseball_milbbaseball_mlb_world_series_winnerIce Hockey
icehockey_nhlicehockey_sweden_hockey_leagueicehockey_ahlicehockey_nhl_preseasonicehockey_sweden_allsvenskanicehockey_nhl_championship_winnerSoccer
soccer_eplsoccer_uefa_champs_leaguesoccer_germany_bundesligasoccer_italy_serie_asoccer_spain_la_ligasoccer_france_ligue_onesoccer_uefa_europa_leaguesoccer_usa_mlssoccer_conmebol_copa_libertadoressoccer_conmebol_copa_americasoccer_netherlands_eredivisiesoccer_portugal_primeira_ligasoccer_brazil_campeonatosoccer_mexico_ligamxsoccer_efl_champsoccer_fa_cupsoccer_uefa_europa_conference_leaguesoccer_fifa_world_cupsoccer_fifa_club_world_cupsoccer_england_league1soccer_england_league2soccer_scotland_premiershipsoccer_turkey_super_leaguesoccer_belgium_first_divsoccer_japan_j_leaguesoccer_korea_kleague1soccer_argentina_primera_divisionsoccer_brazil_serie_bsoccer_chile_campeonatosoccer_china_superleaguesoccer_conmebol_copa_sudamericanasoccer_finland_veikkausliigasoccer_germany_dfb_pokalsoccer_league_of_irelandsoccer_norway_eliteseriensoccer_saudi_arabia_pro_leaguesoccer_spain_segunda_divisionsoccer_sweden_allsvenskansoccer_sweden_superettansoccer_fifa_world_cup_winnersoccer_germany_bundesliga2soccer_germany_liga3soccer_italy_serie_bsoccer_france_ligue_twosoccer_austria_bundesligasoccer_switzerland_superleaguesoccer_denmark_superligasoccer_greece_super_leaguesoccer_poland_ekstraklasasoccer_uefa_nations_leaguesoccer_uefa_european_championshipsoccer_uefa_euro_qualificationsoccer_uefa_champs_league_qualificationsoccer_africa_cup_of_nationsCombat Sports
mma_mixed_martial_artsboxing_boxingRugby Union
rugbyunion_six_nationsrugbyunion_world_cuprugbyunion_epcr_champions_cupCricket
cricket_iplcricket_test_matchcricket_international_t20cricket_t20_world_cupcricket_icc_world_cupcricket_odicricket_pslcricket_caribbean_premier_leaguecricket_t20_blastcricket_the_hundredcricket_t20_world_cup_womensTennis
tennis_atp_aus_open_singlestennis_atp_wimbledontennis_atp_us_opentennis_atp_french_opentennis_wta_aus_open_singlestennis_wta_wimbledontennis_wta_us_opentennis_wta_french_opentennis_atp_indian_wellstennis_atp_miami_opentennis_atp_madrid_opentennis_atp_canadian_opentennis_atp_cincinnati_opentennis_wta_indian_wellstennis_wta_miami_opentennis_wta_madrid_opentennis_wta_canadian_opentennis_atp_monte_carlo_masterstennis_atp_shanghai_masterstennis_atp_paris_masterstennis_atp_italian_opentennis_wta_italian_opentennis_atp_hamburg_opentennis_wta_strasbourg_opentennis_atp_geneva_opentennis_atp_halle_opentennis_atp_queens_club_champtennis_wta_german_openGolf
golf_masters_tournament_winnergolf_pga_championship_winnergolf_the_open_championship_winnergolf_us_open_winnergolf_pga_tour_winnerDarts
darts_betpt_dartsdarts_dartsSnooker
snooker_worldchampssnooker_snookerEsports
esports_lol_worldsesports_csgoesports_csgo_esl_pro_leagueesports_valorantesports_valorant_vct_championsesports_dota2esports_lolMotorsport
motorsport_formula_1_winnermotorsport_nascar_cup_seriesCycling
cycling_tour_de_france_winnercycling_vuelta_espana_winnercycling_giro_ditalia_winnerHandball
handball_germany_bundesligaVolleyball
volleyball_brazil_superligaLacrosse
lacrosse_plllacrosse_ncaa🟢 High AU coverage = 10+ bookmakers price this regularly. 🟡 Medium = 4–9 bookmakers. 🔴 Low = 1–3 bookmakers.
Australian Bookmakers
All prices are collected from the au region. These are the bookmaker keys returned in API responses. The exchange price appears as betfairexau in raw data and is used as a sharp benchmark for fair-price calculation.
/api/v1/opportunities/player-propsReturns one-sided player prop opportunities (+EV over/under entries as separate records), with optional historical hit rate data. Covers NBA, NFL, AFL, NRL, MLB, NHL, and all major sports.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| sport | string | No | Filter by sport key (basketball_nba, aussierules_afl, rugbyleague_nrl, etc.) |
| market | string | No | Prop market (player_points, player_rebounds, player_assists, player_disposals, player_tackles, etc.) |
| player | string | No | Filter by player name (partial match supported) |
| min_ev | number | No | Minimum EV percentage (e.g., 3.0 for +3% EV or better) |
| include_stats | boolean | No | Include historical hit rates and player statistics (all tiers) |
| limit | number | No | Results per page (max based on your tier) |
Response Schema
| Field | Type | Description |
|---|---|---|
| id | string | Unique prop identifier |
| sport | string | Sport name (e.g. "NBA") |
| sport_key | string | Sport key for filtering |
| event | string | Event description |
| player_name | string | Player name |
| market_key | string | Prop market key |
| line | number | Over/Under line |
| side | string | "over" or "under" for this record |
| odds | number | Decimal odds for this side |
| bookmaker | string | Bookmaker for this side |
| ev_percentage | number | Expected value percentage for this side |
| commence_time | ISO 8601 | When the event starts |
| historical_stats | object | Historical performance data (if include_stats=true) |
Example Request
GET /api/v1/opportunities/player-props?sport=basketball_nba&min_ev=3&include_stats=true&limit=10 Headers: X-API-Key: YOUR_API_KEY_HERE
Example Response
{
"success": true,
"data": [
{
"id": "prop_xyz789",
"sport": "NBA",
"sport_key": "basketball_nba",
"event": "Lakers vs Warriors",
"player_name": "LeBron James",
"market_key": "player_points",
"line": 25.5,
"side": "over",
"odds": 1.90,
"bookmaker": "Bet365",
"ev_percentage": 4.2,
"commence_time": "2026-03-03T19:00:00Z",
"historical_stats": {
"hit_rate_over": 70,
"hit_rate_under": 30,
"last_10_games": [28, 31, 19, 33, 28, 24, 30, 22, 35, 26],
"streak": "over_3",
"home_rate": 75,
"away_rate": 58
}
}
],
"meta": {
"count": 147,
"timestamp": "2026-03-02T10:30:00Z",
"rate_limit": {
"limit": 100,
"remaining": 95,
"reset": "2026-03-02T11:00:00Z"
}
}
}💡 Pro Tip: Use include_stats=true to get historical hit rates, last 10 game results, current streaks, and home/away splits for better betting decisions.
/api/v1/opportunities/sgm-picksUpcoming data-backed same-game multi suggestions (safe / value / longshot tiers), with legs, fair odds, minimum acceptable price, and confidence. Only events with commence_time in the future are returned.
Query Parameters
sport/sport_key— filter by sport keytier—safe,value, orlongshotmin_confidence— 1–5 (default 1)limit— max rows (tier caps: free 50, api 200; default 20)
GET /api/v1/opportunities/sgm-picks?sport_key=aussierules_afl&tier=safe&min_confidence=3&limit=20 X-API-Key: YOUR_API_KEY
Tiers & Rate Limits
Billing is metered in credits, not raw requests. Each endpoint declares a cost; the monthly cap and overage are both denominated in credits. Empty results are refunded.
Arbitrage + low-hold opportunities. 50 requests per month, 5 results per request. Sign in required — no credit card.
Full API — arbitrage, EV, middles, player props, racing, exchange pricing, scraped odds feed, webhooks, bulk export. 50,000 requests per month, 500 results per request. Priority support. Optional overage billing available.
X-RateLimit-Tier: api\nX-RateLimit-Limit: 500\nX-Credits-Cost: 1\nX-Credits-Remaining: 49999\nX-Credits-Reset: 2026-09-01
Credit Costs by Endpoint
Not all requests cost the same. Endpoints are grouped by data complexity:
Example: 50K credits/month = 50K standard requests, or 10K archive requests, or 2K bulk requests. Mixed usage is naturally balanced.
Optional Overage Billing
API tier subscribers can enable optional overage billing for requests beyond the 50,000 monthly included limit. Overage is billed at A$0.005 per credit (A$5 per 1,000 credits).
- Overage is opt-in only — not enabled by default
- Enable/disable via the API dashboard or the
/api/api-keys/overageendpoint - Set a spending cap to limit max overage per billing period
- Overage usage is reported in real-time and billed at your billing cycle end
- Free tier users are not eligible for overage billing
📛 Error Codes
The API uses standard HTTP status codes to indicate success or failure. All error responses include a { success: false, error: "message" } body.
| Code | Meaning | Common Causes | Solution |
|---|---|---|---|
| 200 | Success | Request completed successfully | Parse the response data |
| 400 | Bad Request | Invalid parameters, malformed query | Check parameter names and values match documentation |
| 401 | Unauthorized | Missing or invalid API key | Ensure X-API-Key header is set correctly |
| 403 | Forbidden | API key doesn't have permission | Verify your subscription tier includes this endpoint |
| 429 | Too Many Requests | Rate limit exceeded | Wait until X-RateLimit-Reset time, or upgrade tier |
| 500 | Internal Server Error | Server-side issue | Retry request; contact support if persists |
| 503 | Service Unavailable | Maintenance or temporary outage | Check status page, retry with exponential backoff |
All errors return a consistent JSON shape:
{
"success": false,
"error": "Monthly request limit exceeded"
}💻 Code Examples
💻 Code Examples
Fetching Arbitrage Opportunities
These examples use the dedicated endpoint /opportunities/arbitrage, which returns a flat array in data. If you use /opportunities?type=arbs, read from data.arbs instead.
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://krokodds.com.au/api/v1"
headers = {
"X-API-Key": API_KEY
}
response = requests.get(
f"{BASE_URL}/opportunities/arbitrage",
headers=headers,
params={
"sport": "basketball_nba",
"min_value": 2.0,
"limit": 20
}
)
if response.status_code == 200:
data = response.json()
for arb in data["data"]:
print(f"Event: {arb['event']}")
print(f"Value: {arb['value']}% profit")
print(f"{arb['bookmaker1']}: {arb['odds1']}")
print(f"{arb['bookmaker2']}: {arb['odds2']}")
print("---")
else:
print(f"Error: {response.status_code} - {response.json()['error']}")Fetching Player Props with Statistics
import requests
r = requests.get("https://krokodds.com.au/api/v1/opportunities/player-props",
headers={"X-API-Key": API_KEY},
params={"sport": "basketball_nba", "player": "LeBron", "min_ev": 3, "include_stats": True, "limit": 10})
for prop in r.json()["data"]:
print(prop["player_name"], prop["market_key"], prop["side"], prop["ev_percentage"])All API keys support webhooks. Contact [email protected] to configure.
// Express.js webhook example
app.post('/webhook/krok', (req, res) => {
const { type, event, value, bookmaker1, bookmaker2, odds1, odds2 } = req.body
if (type === 'arb_alert' && value >= 3.5) {
console.log(`ARB: ${event} — ${bookmaker1} vs ${bookmaker2} — ROI: ${value.toFixed(2)}%`)
// your bet placement logic here
}
res.sendStatus(200)
})📋 Changelog
📋 Changelog
- 🆕NEW:
/v1/racing/meetingsrunners now includeclass_profile(current_rating, peak_rating, highest_class_won, optimal_range_min, optimal_range_max, trend) — the runner's class rating profile - 🆕NEW:
/v1/racing/runner-formentries now includeclass_conditions— the race class text (e.g. "BM58", "Maiden", "3-4YO BM68") for each past start - 📈IMPROVED:
/v1/racing/meetingsrunners now includehorse_code— use it to call/v1/racing/sectionals/{horseCode}for sectional timing & horse profile data - 📈IMPROVED:
/v1/racing/meetingsrunners now includepace_band(measured early-speed band) andclaim(apprentice claim in kg) - 📈IMPROVED:
/v1/racing/runner-statssplits now includeclass_change(up/down/same/new_count tallies);by_prep_stage(first_up/second_up/in_prep) is now documented - 🐛FIX:
/v1/f1/racesand/v1/f1/resultscorrected to be available on all tiers (previously mis-gated as paid-only) - 📈IMPROVED:
/v1/racing/meetingsrunners now includebarrier,jockey,trainer,weightandformon covered Australian meetings - 📈IMPROVED:
/v1/statusis now rate-limited like all other endpoints - 🐛FIX: documentation corrections — tier badges, per-request limits and cache windows now match live enforcement
- ✨NEW:
/v1/exchange— full exchange pricing suite (Pro+) multiplexed bysource: settledbsp,results,match_odds,scorer_props, livesnapshots - ✨NEW:
/v1/bulk— API-plan cursor-paginated whole-collection archive export for model training (manifest + 13 datasets) - 📈IMPROVED:
/v1/advanced-statsaddsmlb_advancedsource (exit velo, barrel%, xwOBA); injury feed now its owninjuriesentitlement
- ✨NEW:
/v1/tips— daily ML game picks with confidence 1–5, consensus probabilities, predicted margin; flips to settled tips viainclude_settled=true - ✨NEW:
/v1/results— final scores with server-derived winner (home/away/draw); filter bysport_key+since - ✨NEW:
/v1/injuries— current player injury feed with status, reason, season; updated-at sorted - ✨NEW:
/v1/racing/meetings— today's T/H/G meetings + race cards withnext_jumpand per-race runner counts - 🎯LIVE:
/v1/racing/arbsand/v1/racing/moversare now connected to the live racing feed (no longer “coming soon”) - 📈IMPROVED: SGM picks pre-filter pool now tier-aware (free 30, api 3000) so high-tier callers no longer miss top-confidence picks beyond the legacy 300 cap
- ✨NEW: Player props endpoint with historical hit rates, last 10 games, streaks, and home/away splits
- 🎯IMPROVED: Response times reduced by 40% across all endpoints through optimized queries
- 📈IMPROVED: Uniform ~60-second refresh across all 156 sports for live and upcoming markets (futures/preseason every ~10 min)
- 🐛FIX: Odds formatting now consistent (always 2 decimal places) across all endpoints
- ✨NEW: Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset)
- 🎯IMPROVED: Better error messages with specific guidance on how to resolve issues
- 🐛FIX: Timestamp format now consistent (ISO 8601) across all responses
- ✨NEW: Initial API launch with arbitrage, positive EV, middles, and low holds endpoints
- ✨NEW: Support for 12+ major sports including NBA, NFL, AFL, NRL, EPL, and more
Need custom endpoints, extra credits, or data we don't list yet?
We're happy to work something out. Contact sales — we can tailor a plan to fit your use case.