Krok Odds
API

Krok Odds API

Real-time arbitrage, positive EV, middle, and racing edge data for Australian sports markets — updated every 60 seconds across 100+ 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 100+ bookmakers every 30 seconds across 135 sports. 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 (snaps):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 (dashboard only):Best fixed-odds across AU books vs the licensed exchange lay price. Available in the web dashboard. Dedicated API endpoints are coming soon.

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 snap. If two bookies combined imply <100% probability, that's an arb.

Bookmaker Coverage

Every book Krok Odds prices, across all feeds — The Odds API, RapidOdds, Betfair 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.

123 branded sites covered21 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 (hobby / pro / enterprise)
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 snaps, middles, low holds, racing edges, and player props — all filtered and sorted by value. Results are cached server-side per tier: Hobby 60s · Pro 30s · Enterprise 15s.

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 your tier: Hobby=100, Pro=500, Enterprise=10,000.
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=arbsHobby+ · 60/30/15s
/api/v1/opportunities/low-holds?type=low_holdsHobby+ · 60/30/15s
/api/v1/opportunities/positive-ev?type=snipesPro+ · 300s
/api/v1/opportunities/middles?type=middlesPro+ · 300s
/api/v1/opportunities/player-props?type=playerpropsPro+ · see below

Racing

Australian thoroughbred (T), harness (H), and greyhound (G) coverage. Three live endpoints: arbs, movers, and meetings.

GET /api/v1/racing/arbsEnterprise

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 (tier-capped: 100 / 500 / 10000).

{
  "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": "Bet365",
      "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": "pro",
    "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/moversEnterprise

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 (tier-capped: 100 / 500 / 10000).

GET /api/v1/racing/meetingsEnterprise

Today's meetings + full race cards. Each meeting includes BOM weather observation, BOM 7-day forecast, track condition hint, races[] with runner-level fields (barrier, jockey, trainer, weight, form, scratchings, top-of-book win/place, and a per-bookmaker odds[] grid).

GET /api/v1/racing/meetings?race_type=T&venue=flemington&limit=50

Params: race_type (T|H|G), venue (substring), limit (tier-capped: 50 / 200 / 1000). Cache TTL 120 / 60 / 30 seconds. See Racing meeting object below for the full field reference.

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 (tier-capped: 50 / 200 / 1000). Cache TTL 120 / 60 / 30 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
    }
  ]
}

GET /api/v1/results

Final scores for completed games. winner is derived server-side as home, away, or draw.

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 (tier-capped: 100 / 500 / 5000). Cache TTL 300 / 120 / 60 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 (tier-capped: 100 / 500 / 5000). Cache TTL 600 / 300 / 120 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-log

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 (tier-capped: 50 / 200 / 2000). Cache TTL 600 / 300 / 120 seconds.

GET /api/v1/historical/team-game-log

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 (tier-capped: 100 / 500 / 5000). Cache TTL 600 / 300 / 120 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 (tier-capped: 50 / 200 / 2000). Cache TTL 300 / 120 / 60 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 (tier-capped: 50 / 200 / 2000). Cache TTL 120 / 60 / 30 seconds.

GET /api/v1/odds-history

Open/latest/movement summary per event-market-selection. direction is one of drift, shorten, flat. Set include_snapshots=true to also return raw tick history (much larger payload).

GET /api/v1/odds-history?sport_key=basketball_nba&market=h2h&include_snapshots=false&limit=25

Params: sport_key, event_id, market, selection (substring), include_snapshots (boolean), limit (tier-capped: 25 / 100 / 1000). Cache TTL 300 / 120 / 60 seconds.

GET /api/v1/steam-movesPro+

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 (tier-capped: 50 / 200 / 1000). Cache TTL 120 / 60 / 30 seconds.

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 (tier-capped: 50 / 200 / 1000). Cache TTL 600 / 300 / 120 seconds.

GET /api/v1/racing/resultsEnterprise

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 (tier-capped: 50 / 200 / 2000). Cache TTL 600 / 300 / 120 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 (tier-capped: 100 / 500 / 5000). 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 (The Odds API, RapidOdds, Betfair, TAB 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. Tier caps 100/500/10000.

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. Tier caps 50/200/2000. Cache 300/120/60s.

GET /api/v1/gameday/summaries

Editorial summaries (headline + storylines + best price snapshot) keyed by event. Filter by sport_key or event_id. Tier caps 50/200/2000. Cache 600/300/120s.

GET /api/v1/gameday/alt-lines

Alternative-line ladders for spread + total markets. best_by_line keyed {market}|{line}. Tier caps 50/200/2000. Cache 300/120/60s.

GET /api/v1/extended-markets

Net-new derivative markets sourced beyond The Odds API — 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). Pro+. Tier caps 50/200/2000. Cache 300/120/60s.

GET /api/v1/gameday/live

In-play score + status snapshot. Filter by status (pre/live/final). Fastest TTL on the platform — cache 60/30/15s. Tier caps 50/200/2000.

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 300/120/60s.

GET /api/v1/player-props-stats

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. Tier caps 50/200/2000. Cache 600/300/120s.

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). Tier caps 50/200/2000. Cache 600/300/120s.

GET /api/v1/racing/runner-formEnterprise

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). Tier caps 50/200/2000. Cache 600/300/120s.

GET /api/v1/sport-activity

Per-sport "is this active right now" flag with has_outrights. Filter by sport_key, group, or active=true. Tier caps 100/500/5000. 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). Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/opportunity-history

Read-side archive of expired opportunities. type filter (arb/ev), sport_key, since. Records cleaned up after 24h — backtest only. Tier caps 50/200/2000. Cache 300/120/60s.

GET /api/v1/closing-linesPro+

Closing-line snapshots for settled events — the consensus price at market close, for CLV backtesting. Filter by sport_key, event_id (direct doc fetch), or since. Tier caps 50/200/2000. Cache 600/300/120s.

GET /api/v1/weatherPro+

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. Tier caps 100/500/5000. Cache 1800/600/300s.

GET /api/v1/stream/opportunitiesPro+

Server-Sent Events (SSE) live push of new arb/EV/middle/low-hold opportunities as they land — no polling. Content-Type: text/event-stream; each data: frame is one opportunity JSON. Filter by type, sport_key. Connection held open; reconnect with Last-Event-ID. Streaming is Pro+.

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. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/mma/fights

Upcoming + completed MMA fight cards (UFC, Bellator, PFL). Filter by fight_id or since. Tier caps 50/200/2000. Cache 1800/600/300s.

GET /api/v1/f1/races

F1 race calendar with weather + circuit metadata. Filter by race_id, season, since. Tier caps 50/200/2000. Cache 1800/600/300s.

GET /api/v1/historical/player-statsPro+

Full player historical profiles: season averages, splits, coverage windows, market lines. sport_key required; slug (single player) and team (in-memory filter) optional. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/historical/aflPro+

AFL archive (akareen + AFL Tables). kind=player (player game logs) or kind=match (results). Optional year; round (player only, in-memory). Matches 2010-2017 served from AFL Tables backfill (pass year), 2018+ from akareen. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/historical/nrlPro+

NRL archive. kind=player / match (uselessnrlstats, 2010-2023) or kind=modern (NRL Match Centre, 2024+). Optional season. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/soccer/closing-oddsPro+

Soccer match results with opening + closing odds across 6 leagues. league_code and/or season (string, e.g. 2021-2022). Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/advanced-statsPro+

Advanced / model-grade metrics by source: mlb_advanced (exit velo, barrel%, xwOBA — filter team/playerType), nhl_skaters (Corsi/Fenwick/PDO), ncaab_schools, soccer_xg, ncaaf_player_games, nfl_ngs (player tracking), nfl_snaps, nfl_depth, soccer_fbref (FBref per-season xG/npxG/xA + progressive carries — filter league/compId/sportKey/squad; attribution: “Data Provided by Sports Reference, LLC”), nrl_player_games (per-match NRL player stat lines — filter round/teamNickname/playerSlug), afl_matches (AFL match results w/ quarter-by-quarter goals/behinds — season maps to year, filter team1/team2/venue), tennis_closing_odds (Bet365 + Pinnacle closing odds per ATP/WTA match — season maps to year, filter tour/surface/round), nhl_moneypuck_skaters (MoneyPuck xG/Corsi/high-danger per skater season — filter team/position/playerSlug), nhl_moneypuck_goalies (MoneyPuck GSAx + danger-state goals against — filter team/playerSlug). season equality + source-specific in-memory filters (team/opponent/flavor/league/playerType/squad/round/tour/surface/venue). Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/cricket/inningsPro+

Ball-by-ball derived player innings (batting + bowling). sport_key, match_type (T20/ODI/Test), or season (string) — at least one required. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/tennis/matchesPro+

ATP + WTA singles results. season (number); tour + surface narrow in-memory. Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/f1/resultsPro+

F1 driver race results (distinct from /f1/races schedule). season (number) + round (in-memory). Tier caps 100/500/5000. Cache 3600/1800/600s.

GET /api/v1/exchangePro+

Exchange pricing suite, one endpoint multiplexed by source: bsp (settled Starting Price — the sharpest AU racing closing price, filter raceKey/venueSlug/marketType), results (winners/losers/removed, filter raceKey), match_odds (exchange-implied h2h probs, equality sport + eventId), scorer_props (equality sport + eventId/marketType), snapshots (live pre-jump back/lay, equality sport + eventId). Tier caps 100/500/5000. Cache 600/300/120s.

GET /api/v1/exchange?source=bsp&venueSlug=randwick&limit=50

GET /api/v1/bulkEnterprise

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. Tier caps 1000/1000/5000 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/reference/headshots

Static player headshot URLs (all tiers incl. Hobby). sport_key required; slug optional (single player). Returns name/slug/photo_url/source. Tier caps 200/1000/5000. Cache 86400/43200/21600s.

GET /api/v1/reference/team-logos

Static team logo URLs + name aliases (all tiers incl. Hobby). sport_key required. Returns names/logo/external_id/source. Tier caps 200/1000/5000. Cache 86400/43200/21600s.

GET /api/v1/predictionsPro+

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. Tier caps 100/500/5000. 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": "pro",
    "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 (Pro + Enterprise)

Receive real-time HTTP POST notifications when new opportunities are detected. Requires a Pro or Enterprise API plan.

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": "pro",
    "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": "pro",
    "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",
      "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",
      "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,
          "runners": [
            {
              "id": "r7",
              "number": 7,
              "name": "Gatwick",
              "barrier": 3,
              "jockey": "J. McNeil",
              "trainer": "C. Maher",
              "weight": 57.5,
              "form": "1-2-4",
              "is_scratched": false,
              "best_win": 6.50,
              "best_win_bookmaker": "Sportsbet",
              "implied_prob": 0.154,
              "odds": [
                { "bookmaker": "Sportsbet", "win": 6.50, "place": 2.20 },
                { "bookmaker": "Bet365",    "win": 6.00, "place": 2.10 }
              ]
            }
          ]
        }
      ]
    }
  ],
  "meta": {
    "count": 1,
    "tier": "pro",
    "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.
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.
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, runners[].
races[].runners[]arrayRunners. Each: id, number, name, barrier, jockey, trainer, weight, form, is_scratched, best_win, best_win_bookmaker, implied_prob, 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"
}

Returns the top 20 trending value picks (arbs, EV bets, middles) ranked by composite score across our tools. Requires an active session (dashboard users only — not accessible via API key). Refreshed by cron throughout the day.

GET https://krokodds.com.au/api/trending
{
  "trending": [
    {
      "id": "trending_0",
      "rank": 1,
      "event": "Cowboys vs Knights",
      "sport": "NRL",
      "sportkey": "rugbyleague_nrl",
      "market": "h2h",
      "toolType": "arb",
      "bookmaker1": "Sportsbet",
      "bookmaker2": "TAB",
      "selection1": "Cowboys",
      "selection2": "Knights",
      "odds1": 2.10,
      "odds2": 2.05,
      "value": 1.8,
      "commencetime": "2026-03-01T08:00:00Z"
    }
  ]
}

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 135 sports — live and upcoming markets refresh every ~60 seconds. 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

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

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

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_rome_open
🟡 AUT3
🎾
Italian Open (WTA)
tennis_wta_rome_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

🟢 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
NEWPro+GET/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 (Pro tier and above only)
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 (Pro tier+) to get historical hit rates, last 10 game results, current streaks, and home/away splits for better betting decisions.

GET/api/v1/opportunities/sgm-picksPro+

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: hobby 50, pro 200, enterprise 1000; 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

Response headers always include your current tier and request limit so you can track usage programmatically.

Hobby
A$29/mo
A$23/mo ($276/year — save $72)
Per request: 100 results
Monthly: 500 requests

Arbitrage + low-hold only, plus reference data (team logos + player headshots). 100+ AU corporate bookmakers (no exchange pricing). 500 API requests per month. 100 results per request max.

Most Popular
Pro
A$99/mo
A$79/mo ($948/year — save $240)
Per request: 500 results
Monthly: 10,000 requests

Everything in Hobby + EV, middles, player props, steam moves, predictions, webhooks, gameday analysis, injury feed, plus the full exchange pricing suite (BSP, match-odds, scorer props, live snapshots, results) and full historical + advanced/modeling-stats + multi-sport archives (player stats, AFL/NRL, soccer closing odds, MLB advanced batted-ball, NHL/NFL/NCAA advanced, NFL player tracking, cricket, tennis, F1). 10,000 API requests per month. 500 results per request max.

Enterprise
A$249/mo
A$199/mo ($2,390/year — save $598)
Per request: 10,000 results
Monthly: 100,000 requests

Everything in Pro + AU racing (thoroughbred, harness, greyhound arbs/movers/form) and bulk dataset export (cursor-paginated whole-collection archive dumps for model training), 100,000 API requests per month, 10,000 results per request, priority support.

X-RateLimit-Tier: pro
X-RateLimit-Limit: 300

📛 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"])

Pro and Enterprise API keys support webhooks. Contact contact@krokodds.com.au 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

June 2026LATEST
  • NEW: /v1/exchange — full exchange pricing suite (Pro+) multiplexed by source: settled bsp, results, match_odds, scorer_props, live snapshots
  • NEW: /v1/bulk — Enterprise 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 (hobby 300, pro 1000, enterprise 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 135 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