Krok Odds
API

Krok Odds API

Real-time arbitrage, positive EV, middle, and racing edge data for Australian sports markets — updated every few minutes across 140+ bookmakers.

Base URL
krokodds.com.au
Protocol
HTTPS only
Format
JSON
Auth
API Key

⚡ Quick Start (5 Minutes)

1

Get Your API Key

Visit /api-dashboard and click "Create API Key". Copy the key — you'll need it for authentication.

2

Make Your First Request

curl https://krokodds.com.au/api/v1/opportunities/arbitrage?limit=5 \
  -H "X-API-Key: YOUR_API_KEY_HERE"
3

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"
  }
}
4

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.

143 branded sites covered27 distinct price linesClone brands on an aggregator platform share one odds line — coverage breadth, not extra prices.

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
Never expose your API key in frontend code or public repos. Always call the API from a backend server or serverless function.
Sport filtering: You can filter by either 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:

HeaderDescription
X-RateLimit-TierYour plan tier (free / api)
X-RateLimit-LimitMax results per request for your tier
X-RateLimit-RemainingRequests remaining this month
X-RateLimit-ResetDate 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

ParameterTypeRequiredDefaultDescription
typestringrequiredallWhich opportunity type to return. One of: all · arbs · snipes · middles · low_holds · racing · playerprops. positive-ev is accepted as an alias for snipes.
sportstringoptional(all sports)Filter by sport label (e.g. AFL, NBA, NRL, EPL). Case-insensitive.
sport_keystringoptional(none)Filter by internal sport key (e.g. aussierules_afl, basketball_nba). More precise than sport — use this when targeting a specific league.
minvaluenumberoptional0Minimum edge / ROI % to include. e.g. 2.0 returns only arbs ≥2% ROI.
limitintegeroptional100Max results per type. Capped by tier: Free=100, API=500.
apikeystringoptionalYour 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.

EndpointAggregated equivalentTier · Cache
/api/v1/opportunities/arbitrage?type=arbsAll tiers · 300s
/api/v1/opportunities/low-holds?type=low_holdsAll tiers · 300s
/api/v1/opportunities/positive-ev?type=snipesAll tiers · 300s
/api/v1/opportunities/middles?type=middlesAll tiers · 300s
/api/v1/opportunities/player-props?type=playerpropsAll 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

ParameterTypeDefaultDescription
sport_keystringFilter by sport (e.g. basketball_nba)
sportstringFilter by sport label (e.g. NBA)
bookmakerstringFilter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2.
min_valuenumber0Minimum edge/ROI %
limitinteger100Max results (cap 10000)
cursorstringPagination cursor
fieldsstringComma-separated fields to include

/opportunities/positive-ev — query filters

ParameterTypeDefaultDescription
sport_keystringFilter by sport (e.g. basketball_nba)
sportstringFilter by sport label (e.g. NBA)
bookmakerstringFilter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2.
min_valuenumber0Minimum edge/ROI %
limitinteger100Max results (cap 10000)
cursorstringPagination cursor
fieldsstringComma-separated fields to include

/opportunities/low-holds — query filters

ParameterTypeDefaultDescription
sport_keystringFilter by sport (e.g. basketball_nba)
sportstringFilter by sport label (e.g. NBA)
bookmakerstringFilter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2.
min_valuenumber0Minimum edge/ROI %
max_holdnumberMaximum hold % to include
limitinteger100Max results (cap 10000)
cursorstringPagination cursor
fieldsstringComma-separated fields to include

/opportunities/middles — query filters

ParameterTypeDefaultDescription
sport_keystringFilter by sport (e.g. basketball_nba)
sportstringFilter by sport label (e.g. NBA)
bookmakerstringFilter by bookmaker name (e.g. sportsbet). Matches either bookmaker1 or bookmaker2.
min_valuenumber0Minimum edge/ROI %
limitinteger100Max results (cap 10000)
cursorstringPagination cursor
fieldsstringComma-separated fields to include

/opportunities/player-props — query filters

ParameterTypeDefaultDescription
sport_keystringFilter by sport
playerstringFilter by player name (substring match)
bookmakerstringFilter by bookmaker
marketstringFilter by market type
min_evnumber0Minimum EV percentage
limitinteger100Max results

/opportunities/sgm-picks — query filters

ParameterTypeDefaultDescription
sport_keystringFilter by sport
tierstringRisk tier (safe/balanced/aggressive)
min_confidencenumberMinimum confidence (1-5)
limitintegerMax 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

ParameterTypeDefaultDescription
sport_keystringFilter by sport
event_idstringFilter by event
directionstringshortening or drifting
min_move_pctnumberMinimum move percentage
bookmakerstringFilter by bookmaker
limitintegerMax 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

ParameterTypeDescription
apikeystringRequired. Your API key (or X-API-Key header)
categorystringFilter 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

ParameterTypeDefaultDescription
sport_keystringFilter by sport
player_slugstringFilter by player slug
player_canonicalstringFilter by canonical name
market_keystringFilter by market
sidestringover or under
limitintegerMax 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

ParameterTypeDefaultDescription
sport_keystringFilter by sport
event_idstringFilter by event
player_namestringFilter by player name (substring)
marketstringFilter by market type
limitintegerMax 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).

FieldTypeDescription
modelstringModel name used for rating generation (e.g. krok_v3).
ratings_versionstringVersion tag for the ratings pipeline.
race_idstringRace identifier.
meeting_idstringParent meeting identifier.
top_pickobjectRunner object of the top-rated runner.
scorenumberComposite confidence score for the top pick.
tierstringRating tier (e.g. strong, moderate, marginal).
breakdownobjectPer-component score breakdown. Sub-fields: career, track, distance, form, valueGap, freshness, classFit, weightEdge, barrier, connections — each a numeric score.
top_analysisstringNarrative analysis of the top pick.
field_analysisstringNarrative analysis of the full field.
riskstringRisk assessment for the top pick.
track_conditionstring | nullTrack condition at time of race.
weatherstring | nullWeather at time of race.
value_picksarrayArray of value-rated runners.
market_moverobject | nullBiggest market mover in the field.
pick_rationalestring | nullOne-liner AI rationale for why this runner was selected.
resultstring | nullSettlement result: win, place, loss, pending.
winning_slugstring | nullSlug of the winning runner.
race_namestringName of the race.
race_numbernumberRace number.
venuestringVenue name.
statestring | nullState code.
race_typestringT/H/G.
jump_timestringScheduled jump time.
datestringRace date.
confidencestringHigh or low confidence rating.
runnersarrayPer-runner rating details (see below).

Per-runner fields

FieldTypeDescription
win_probnumberModel win probability (0-1).
fair_oddsnumberFair decimal odds (1/win_prob).
confidencenumberPer-runner confidence score.
ranknumberRunner rank in the field (1 = top pick).
edge_pctnumberEdge percentage over the market price.
valuenumberValue rating score.
money_sharenumberBetfair money share (0-1).
money_deltanumberBetfair money flow delta.
ratingnumberComposite 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).

FieldTypeDescription
slugstringMatched TAB slug for this connection.
matched_slugstringWhich slug variant answered (full name or abbreviated form).
namestringDisplay name.
typestringjockey or trainer.
startsnumberTotal career starts (as jockey or trainer).
winsnumberTotal career wins.
win_pctnumberWin percentage (0–100).
place_pctnumberPlace percentage (0–100).
roinumberReturn on investment % (flat win).
recent_formarrayLast 10 results: W/P/L.
track_statsarrayPer-venue breakdown: array of {venue, starts, wins, places, win_pct} — shows strike rate at each track.
racing_com_profileobject | nullRacing.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

ParameterTypeDefaultDescription
typesstringComma-separated filter: arbs, snipes, middles, low_holds (default: all four)
sport_keystringFilter by sport
min_valuenumberMinimum 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.

sourceExtra filtersDescription
mlb_advancedteam, playerTypeMLB batted-ball metrics (exit velocity, barrel rate, expected outcomes).
nhl_skatersNHL skater advanced metrics.
ncaab_schoolsCollege basketball team advanced stats.
soccer_xgSoccer expected goals (xG) by player.
ncaaf_player_gamesCollege football player game logs.
nfl_ngsNFL Next Gen Stats tracking data.
nfl_snapsNFL snap count data.
nfl_depthNFL depth charts.
soccer_fbrefleague, compId, sportKey, squadSoccer player season stats (xG/npxG/xA + progressive carries).
nrl_player_gamesround, teamNickname, playerSlugNRL player game logs.
afl_matchesseason→year, team1, team2, venueAFL match data.
tennis_closing_oddsseason→year, tour, surface, roundTennis match closing odds.
nhl_moneypuck_skatersteam, position, playerSlugNHL skater analytics (expected goals, Corsi, etc.).
nhl_moneypuck_goaliesteam, playerSlugNHL 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.

sourceExtra filtersDescription
bspraceKey, venueSlug, marketTypeSettled exchange starting prices — the sharpest closing price for racing.
resultsraceKeyRace results with finishing data.
match_oddssport (required) + eventIdMatch odds with implied probabilities across sports.
scorer_propssport (required) + eventId, marketTypePlayer scorer market odds (first goal, anytime scorer, etc.).
snapshotssport (required) + eventIdLive 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"
  }
}
FieldTypeDescription
idstringUnique identifier for this opportunity.
eventstringHuman-readable event name, format: "Home vs Away".
home_teamstring | nullHome team parsed from event string. null if event format unexpected.
away_teamstring | nullAway team parsed from event string. null if event format unexpected.
sportstringSport title, e.g. NRL, AFL, NBA.
sport_keystringSport key, e.g. rugbyleague_nrl.
marketstringMarket type: h2h (moneyline), spreads, totals, or player prop key.
linenumber | nullSpread/total line for spreads/totals/props markets. null for h2h.
selection1stringFirst outcome name, e.g. Bulldogs.
selection2stringSecond outcome name, e.g. Broncos.
bookmaker1stringBookmaker offering selection1 odds.
bookmaker2stringBookmaker offering selection2 odds.
odds1numberDecimal odds for selection1.
odds2numberDecimal odds for selection2.
valuenumberROI % on total stake. e.g. 3.21 = 3.21% guaranteed profit.
tool_typestringAlways surebet for arbs.
statusstringupcoming · live · finished
commence_timeISO 8601Event start time in UTC.
instructionsstringPlain English stake split, e.g. Bet $44.90 @ TAB and $55.10 @ Sportsbet.
updated_atISO 8601When 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"
  }
}
FieldTypeDescription
valuenumberEV %. e.g. 4.72 = you expect +$4.72 per $100 bet over the long run.
sharp_pricenumberThe fair odds (no-vig exchange price or market average). This is your benchmark.
confidencestringhigh = exchange-derived benchmark. lower = market average (less reliable).
home_teamstring | nullHome team parsed from event string.
away_teamstring | nullAway team parsed from event string.
linenumber | nullSpread/total line for spreads/totals/props markets. null for h2h.
bookmaker2stringThe sharp benchmark source: Exchange Fair or Market Avg.
marketstringh2hev for moneyline EV, or a player prop key e.g. playerpoints.
instructionsstringPlain 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"
  }
}
FieldTypeDescription
idstringMeeting id, typically venue_date.
venuestringRace venue, e.g. Flemington.
statestringAU state code, e.g. VIC.
tote_jurisdictionstring | nullTAB tote jurisdiction the pools/dividends were priced under (VIC/NSW/QLD/SA/WA/TAS/ACT/NT); null when no TAB card is joined.
typestringT = Thoroughbred, H = Harness, G = Greyhounds.
datestringMeeting date YYYY-MM-DD.
race_countnumberNumber of races on the card.
next_jumpISO 8601 | nullEarliest future race jump time across the card.
weatherobject | nullLatest BOM observation: summary, temp_c, rain_24h_mm, wind_kmh, wind_dir, station, observed_at.
weather_forecastobject | nullBOM 7-day forecast for the meeting date: min_c, max_c, precis, rain_chance_pct, rain_range_mm, state.
track_hintstring | nullTrack condition hint (e.g. Good 4, Soft 6) when available.
rail_positionstring | nullRail position (e.g. True 3m, Out 8m) when available.
exotic_poolsobject | nullMeeting-level exotic pool totals: trifecta, first4, quadrella (dollar amounts).
barrier_biasarray | nullHistorical 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_atISO 8601 | nullWhen weather payload was last refreshed.
races[]arrayRace 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[]arrayRunners. 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

🏉
AFL
aussierules_afl
🟢 AUT1
🏉
NRL
rugbyleague_nrl
🟢 AUT1
🏏
Big Bash League
cricket_big_bash
🟢 AUT1
A-League
soccer_australia_aleague
🟢 AUT1
🏉
State of Origin
rugbyleague_nrl_state_of_origin
🟢 AUT2
🏀
NBL
basketball_nbl
🟢 AUT2
🏉
Super Rugby
rugbyunion_super_rugby
🟢 AUT2

American Football

🏈
NFL
americanfootball_nfl
🟢 AUT1
🏈
NCAA Football
americanfootball_ncaaf
🟡 AUT2
🏈
CFL
americanfootball_cfl
🟡 AUT3
🏈
UFL
americanfootball_ufl
🔴 AUT3
🏈
NFL Preseason
americanfootball_nfl_preseason
🔴 AUT4
🏈
Super Bowl Winner
americanfootball_nfl_super_bowl_winner
🟡 AUT4
🏈
NCAAF Championship Winner
americanfootball_ncaaf_championship_winner
🔴 AUT4

Basketball

🏀
NBA
basketball_nba
🟢 AUT1
🏀
NCAA Basketball
basketball_ncaab
🟡 AUT2
🏀
EuroLeague
basketball_euroleague
🟡 AUT3
🏀
WNBA
basketball_wnba
🟡 AUT3
🏀
NBA Preseason
basketball_nba_preseason
🔴 AUT4
🏀
NBA Championship Winner
basketball_nba_championship_winner
🟡 AUT4

Baseball

MLB
baseball_mlb
🟢 AUT1
MLB Preseason
baseball_mlb_preseason
🔴 AUT4
KBO (Korea)
baseball_kbo
🔴 AUT4
NPB (Japan)
baseball_npb
🔴 AUT4
NCAA Baseball
baseball_ncaa
🔴 AUT4
MiLB
baseball_milb
🔴 AUT4
World Series Winner
baseball_mlb_world_series_winner
🟡 AUT4

Ice Hockey

🏒
NHL
icehockey_nhl
🟢 AUT1
🏒
SHL (Sweden)
icehockey_sweden_hockey_league
🔴 AUT3
🏒
AHL
icehockey_ahl
🔴 AUT3
🏒
NHL Preseason
icehockey_nhl_preseason
🔴 AUT4
🏒
HockeyAllsvenskan
icehockey_sweden_allsvenskan
🔴 AUT4
🏒
Stanley Cup Winner
icehockey_nhl_championship_winner
🟡 AUT4

Soccer

English Premier League
soccer_epl
🟢 AUT1
Champions League
soccer_uefa_champs_league
🟢 AUT1
Bundesliga
soccer_germany_bundesliga
🟢 AUT2
Serie A
soccer_italy_serie_a
🟢 AUT2
La Liga
soccer_spain_la_liga
🟢 AUT2
Ligue 1
soccer_france_ligue_one
🟡 AUT2
Europa League
soccer_uefa_europa_league
🟡 AUT2
MLS
soccer_usa_mls
🟡 AUT2
Copa Libertadores
soccer_conmebol_copa_libertadores
🟡 AUT3
Copa America
soccer_conmebol_copa_america
🟡 AUT3
Eredivisie
soccer_netherlands_eredivisie
🟡 AUT3
Primeira Liga
soccer_portugal_primeira_liga
🟡 AUT3
Brasileirao
soccer_brazil_campeonato
🔴 AUT3
Liga MX
soccer_mexico_ligamx
🔴 AUT3
Championship
soccer_efl_champ
🟡 AUT3
FA Cup
soccer_fa_cup
🟡 AUT3
Conference League
soccer_uefa_europa_conference_league
🔴 AUT3
FIFA World Cup
soccer_fifa_world_cup
🟢 AUT3
Club World Cup
soccer_fifa_club_world_cup
🟡 AUT3
League One
soccer_england_league1
🔴 AUT4
League Two
soccer_england_league2
🔴 AUT4
Scottish Premiership
soccer_scotland_premiership
🔴 AUT4
Süper Lig
soccer_turkey_super_league
🔴 AUT4
Belgian Pro League
soccer_belgium_first_div
🔴 AUT4
J1 League
soccer_japan_j_league
🔴 AUT4
K League 1
soccer_korea_kleague1
🔴 AUT4
Primera División (Argentina)
soccer_argentina_primera_division
🔴 AUT4
Brazil Série B
soccer_brazil_serie_b
🔴 AUT4
Primera División (Chile)
soccer_chile_campeonato
🔴 AUT4
Chinese Super League
soccer_china_superleague
🔴 AUT4
Copa Sudamericana
soccer_conmebol_copa_sudamericana
🔴 AUT4
Veikkausliiga
soccer_finland_veikkausliiga
🔴 AUT4
DFB-Pokal
soccer_germany_dfb_pokal
🔴 AUT4
League of Ireland
soccer_league_of_ireland
🔴 AUT4
Eliteserien
soccer_norway_eliteserien
🔴 AUT4
Saudi Pro League
soccer_saudi_arabia_pro_league
🔴 AUT4
La Liga 2
soccer_spain_segunda_division
🔴 AUT4
Allsvenskan
soccer_sweden_allsvenskan
🔴 AUT4
Superettan
soccer_sweden_superettan
🔴 AUT4
World Cup Winner
soccer_fifa_world_cup_winner
🟢 AUT4
2. Bundesliga
soccer_germany_bundesliga2
🔴 AUT4
3. Liga
soccer_germany_liga3
🔴 AUT4
Serie B
soccer_italy_serie_b
🔴 AUT4
Ligue 2
soccer_france_ligue_two
🔴 AUT4
Austrian Bundesliga
soccer_austria_bundesliga
🔴 AUT4
Swiss Super League
soccer_switzerland_superleague
🔴 AUT4
Danish Superliga
soccer_denmark_superliga
🔴 AUT4
Greek Super League
soccer_greece_super_league
🔴 AUT4
Ekstraklasa
soccer_poland_ekstraklasa
🔴 AUT4
UEFA Nations League
soccer_uefa_nations_league
🟡 AUT3
UEFA Euro
soccer_uefa_european_championship
🟢 AUT3
Euro Qualifiers
soccer_uefa_euro_qualification
🟡 AUT4
UCL Qualifiers
soccer_uefa_champs_league_qualification
🟡 AUT4
Africa Cup of Nations
soccer_africa_cup_of_nations
🟡 AUT4

Combat Sports

🥊
UFC / MMA
mma_mixed_martial_arts
🟢 AUT2
🥊
Boxing
boxing_boxing
🟢 AUT2

Rugby Union

🏉
Six Nations
rugbyunion_six_nations
🟢 AUT2
🏉
Rugby World Cup
rugbyunion_world_cup
🟢 AUT2
🏉
Champions Cup
rugbyunion_epcr_champions_cup
🟡 AUT2

Cricket

🏏
IPL
cricket_ipl
🟢 AUT2
🏏
Test Cricket
cricket_test_match
🟢 AUT2
🏏
International T20
cricket_international_t20
🟢 AUT2
🏏
T20 World Cup
cricket_t20_world_cup
🟢 AUT2
🏏
ICC World Cup
cricket_icc_world_cup
🟢 AUT2
🏏
ODI Cricket
cricket_odi
🟢 AUT3
🏏
PSL
cricket_psl
🟡 AUT3
🏏
CPL
cricket_caribbean_premier_league
🟡 AUT3
🏏
T20 Blast
cricket_t20_blast
🟡 AUT3
🏏
The Hundred
cricket_the_hundred
🟡 AUT3
🏏
Women's T20 World Cup
cricket_t20_world_cup_womens
🟢 AUT4

Tennis

🎾
Australian Open (ATP)
tennis_atp_aus_open_singles
🟢 AUT2
🎾
Wimbledon (ATP)
tennis_atp_wimbledon
🟢 AUT2
🎾
US Open (ATP)
tennis_atp_us_open
🟢 AUT2
🎾
French Open (ATP)
tennis_atp_french_open
🟢 AUT2
🎾
Australian Open (WTA)
tennis_wta_aus_open_singles
🟢 AUT2
🎾
Wimbledon (WTA)
tennis_wta_wimbledon
🟢 AUT2
🎾
US Open (WTA)
tennis_wta_us_open
🟢 AUT2
🎾
French Open (WTA)
tennis_wta_french_open
🟢 AUT2
🎾
Indian Wells (ATP)
tennis_atp_indian_wells
🟡 AUT3
🎾
Miami Open (ATP)
tennis_atp_miami_open
🟡 AUT3
🎾
Madrid Open (ATP)
tennis_atp_madrid_open
🟡 AUT3
🎾
Canadian Open (ATP)
tennis_atp_canadian_open
🟡 AUT3
🎾
Cincinnati Open (ATP)
tennis_atp_cincinnati_open
🟡 AUT3
🎾
Indian Wells (WTA)
tennis_wta_indian_wells
🟡 AUT3
🎾
Miami Open (WTA)
tennis_wta_miami_open
🟡 AUT3
🎾
Madrid Open (WTA)
tennis_wta_madrid_open
🟡 AUT3
🎾
Canadian Open (WTA)
tennis_wta_canadian_open
🟡 AUT3
🎾
Monte Carlo Masters
tennis_atp_monte_carlo_masters
🟡 AUT3
🎾
Shanghai Masters
tennis_atp_shanghai_masters
🟡 AUT3
🎾
Paris Masters
tennis_atp_paris_masters
🟡 AUT3
🎾
Italian Open (ATP)
tennis_atp_italian_open
🟡 AUT3
🎾
Italian Open (WTA)
tennis_wta_italian_open
🟡 AUT3
🎾
Hamburg Open (ATP)
tennis_atp_hamburg_open
🟡 AUT3
🎾
Strasbourg (WTA)
tennis_wta_strasbourg_open
🟡 AUT3
🎾
Geneva Open (ATP)
tennis_atp_geneva_open
🟡 AUT3
🎾
Halle Open (ATP)
tennis_atp_halle_open
🔴 AUT4
🎾
Queen's Club (ATP)
tennis_atp_queens_club_champ
🔴 AUT4
🎾
German Open (WTA)
tennis_wta_german_open
🔴 AUT4

Golf

The Masters
golf_masters_tournament_winner
🟢 AUT2
PGA Championship
golf_pga_championship_winner
🟢 AUT2
The Open Championship
golf_the_open_championship_winner
🟢 AUT2
US Open (Golf)
golf_us_open_winner
🟢 AUT2
PGA Tour Events
golf_pga_tour_winner
🟢 AUT3

Darts

🎯
Darts (PDC)
darts_betpt_darts
🟢 AUT2
🎯
Darts
darts_darts
🟢 AUT2

Snooker

🎱
Snooker World Champs
snooker_worldchamps
🟢 AUT2
🎱
Snooker
snooker_snooker
🟡 AUT2

Esports

🎮
LoL Worlds
esports_lol_worlds
🟡 AUT3
🎮
CS:GO / CS2
esports_csgo
🟡 AUT3
🎮
CS2 ESL Pro League
esports_csgo_esl_pro_league
🟡 AUT3
🎮
Valorant Champions
esports_valorant
🟡 AUT3
🎮
Valorant VCT
esports_valorant_vct_champions
🟡 AUT3
🎮
Dota 2
esports_dota2
🔴 AUT3
🎮
League of Legends
esports_lol
🟡 AUT3

Motorsport

🏎️
Formula 1
motorsport_formula_1_winner
🟢 AUT3
🏎️
NASCAR Cup
motorsport_nascar_cup_series
🟡 AUT3

Cycling

🚴
Tour de France
cycling_tour_de_france_winner
🟡 AUT4
🚴
Vuelta a España
cycling_vuelta_espana_winner
🔴 AUT4
🚴
Giro d'Italia
cycling_giro_ditalia_winner
🔴 AUT4

Handball

🤾
Handball Bundesliga
handball_germany_bundesliga
🔴 AUT4

Volleyball

🏐
Volleyball Superliga
volleyball_brazil_superliga
🔴 AUT4

Lacrosse

🥍
PLL
lacrosse_pll
🔴 AUT4
🥍
NCAA Lacrosse
lacrosse_ncaa
🔴 AUT4

🟢 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.

Bet365
Betfair
Betr
BetRight
BlueBet
Boombet
Dabble
Ladbrokes
Neds
PalmerBet
PlayUp
Pointsbet
Sportsbet
TAB
TabTouch
Unibet
NEWGET/api/v1/opportunities/player-props

Returns 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

ParameterTypeRequiredDescription
sportstringNoFilter by sport key (basketball_nba, aussierules_afl, rugbyleague_nrl, etc.)
marketstringNoProp market (player_points, player_rebounds, player_assists, player_disposals, player_tackles, etc.)
playerstringNoFilter by player name (partial match supported)
min_evnumberNoMinimum EV percentage (e.g., 3.0 for +3% EV or better)
include_statsbooleanNoInclude historical hit rates and player statistics (all tiers)
limitnumberNoResults per page (max based on your tier)

Response Schema

FieldTypeDescription
idstringUnique prop identifier
sportstringSport name (e.g. "NBA")
sport_keystringSport key for filtering
eventstringEvent description
player_namestringPlayer name
market_keystringProp market key
linenumberOver/Under line
sidestring"over" or "under" for this record
oddsnumberDecimal odds for this side
bookmakerstringBookmaker for this side
ev_percentagenumberExpected value percentage for this side
commence_timeISO 8601When the event starts
historical_statsobjectHistorical 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.

GET/api/v1/opportunities/sgm-picks

Upcoming 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 key
  • tiersafe, value, or longshot
  • min_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.

Free
A$0
Per request: 5 results
Monthly: 50 requests

Arbitrage + low-hold opportunities. 50 requests per month, 5 results per request. Sign in required — no credit card.

Most Popular
API
A$49/mo
A$39/mo ($468/year — save $120)
Per request: 500 results
Monthly: 50,000 requests

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:

Standard — 1 credit
Live/cached endpoints: arbs, EV, middles, player props, racing live data, exchange, predictions, webhooks, reference data.
Archive — 5 credits
Historical data: race results, odds history, player stats, CLV, opportunity history, closing lines.
Bulk — 25 credits
Heavy archive dumps: per-book odds snapshots, full dataset export, CSV export.

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/overage endpoint
  • 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.

CodeMeaningCommon CausesSolution
200SuccessRequest completed successfullyParse the response data
400Bad RequestInvalid parameters, malformed queryCheck parameter names and values match documentation
401UnauthorizedMissing or invalid API keyEnsure X-API-Key header is set correctly
403ForbiddenAPI key doesn't have permissionVerify your subscription tier includes this endpoint
429Too Many RequestsRate limit exceededWait until X-RateLimit-Reset time, or upgrade tier
500Internal Server ErrorServer-side issueRetry request; contact support if persists
503Service UnavailableMaintenance or temporary outageCheck 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

July 2026LATEST
  • 🆕NEW: /v1/racing/meetings runners now include class_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-form entries now include class_conditions — the race class text (e.g. "BM58", "Maiden", "3-4YO BM68") for each past start
  • 📈IMPROVED: /v1/racing/meetings runners now include horse_code — use it to call /v1/racing/sectionals/{horseCode} for sectional timing & horse profile data
  • 📈IMPROVED: /v1/racing/meetings runners now include pace_band (measured early-speed band) and claim (apprentice claim in kg)
  • 📈IMPROVED: /v1/racing/runner-stats splits now include class_change (up/down/same/new_count tallies); by_prep_stage (first_up/second_up/in_prep) is now documented
  • 🐛FIX: /v1/f1/races and /v1/f1/results corrected to be available on all tiers (previously mis-gated as paid-only)
  • 📈IMPROVED: /v1/racing/meetings runners now include barrier, jockey, trainer, weight and form on covered Australian meetings
  • 📈IMPROVED: /v1/status is now rate-limited like all other endpoints
  • 🐛FIX: documentation corrections — tier badges, per-request limits and cache windows now match live enforcement
June 2026
  • NEW: /v1/exchange — full exchange pricing suite (Pro+) multiplexed by source: settled bsp, results, match_odds, scorer_props, live snapshots
  • NEW: /v1/bulk — API-plan cursor-paginated whole-collection archive export for model training (manifest + 13 datasets)
  • 📈IMPROVED: /v1/advanced-stats adds mlb_advanced source (exit velo, barrel%, xwOBA); injury feed now its own injuries entitlement
May 2026
  • NEW: /v1/tips — daily ML game picks with confidence 1–5, consensus probabilities, predicted margin; flips to settled tips via include_settled=true
  • NEW: /v1/results — final scores with server-derived winner (home/away/draw); filter by sport_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 with next_jump and per-race runner counts
  • 🎯LIVE: /v1/racing/arbs and /v1/racing/movers are 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
March 2026
  • 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
February 2026
  • 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
January 2026
  • 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.

Krok Odds API Reference — Endpoints, Auth & Examples | Krok Odds