Krok Odds

Additional Data — History & market movement

The history & market movement half of the Additional Data reference — every route with its parameters, credit cost and a worked example.

4 of 19 endpoints · all categories · get a free API key

GET/api/v1/odds-historyAPI plan

Per-event opening vs. closing H2H odds with movement direction, deduped across re-keyed event ids.

Requires the paid 'api' tier (feature 'historical'). Two backing shapes depending on data source: primary reads the permanent `odds_history` table (snake_case fields, full bookmaker+opening_odds arrays, response includes them raw); fallback (if odds_history empty/errors) reads the legacy `gameday_odds_history` mirror (camelCase opens/latest/snapshots) then the cold archive. Dedup: same fixture can carry multiple event_ids after upstream re-keying — stale rows are filtered out by default via staleFixtureIds() unless include_duplicates=true. Rows that resolve to the same canonical event (`ops.event_aliases`) are one fixture: a multi-day Test match is served once, not once per day of play, and every row carries `canonical_event_id`.

Query parameters
NameTypeRequiredDefaultDescription
sport_keystringNo–Filter by sport key (lowercased).
event_idstringNo–Filter to a single event.
include_snapshotsbooleanNofalseSet "true" to include the full time-series snapshot array (legacy gameday_odds_history source only).
include_duplicatesbooleanNofalseSet "true" to include stale rows for fixtures that were re-keyed with a new event_id upstream (flagged duplicate: true). Default is freshest-row-only.
limitintegerNo25Max rows. Capped at 25 on free tier, 1000 on api tier.
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/odds-history?sport_key=aussierules_afl"
Example response
{
  "success": true,
  "data": [
    {
      "id": "e8f2a1-nrl-2026-09-04",
      "event_id": "e8f2a1",
      "sport_key": "rugbyleague_nrl",
      "home_team": "Penrith Panthers",
      "away_team": "Melbourne Storm",
      "commence_time": "2026-09-04T09:30:00Z",
      "opens": {
        "home": 1.65,
        "away": 2.25,
        "opened_at_ms": null,
        "home_implied_prob": 0.6061,
        "away_implied_prob": 0.4444
      },
      "latest": {
        "home": 1.58,
        "away": 2.45,
        "home_book": "Sportsbet",
        "away_book": "Sportsbet",
        "updated_at_ms": null,
        "home_implied_prob": 0.6329,
        "away_implied_prob": 0.4082
      },
      "movement": {
        "home_delta": -0.07,
        "away_delta": 0.2,
        "home_direction": "shorten",
        "away_direction": "drift"
      },
      "opening_odds": [],
      "bookmakers": [],
      "snapshot_count": 0,
      "updated_at": "2026-09-03T02:11:00.000Z"
    }
  ],
  "meta": {
    "count": 1,
    "tier": "api",
    "limit": 25,
    "requested_limit": 25,
    "include_snapshots": false,
    "include_duplicates": false,
    "duplicates_found": 0,
    "timestamp": "2026-09-03T04:00:00.000Z",
    "rate_limit": {
      "limit": 100,
      "remaining": 4990,
      "reset": "2026-10-01T00:00:00.000Z"
    }
  }
}
GET/api/v1/odds/movementFree tier

Historical odds movement for one event/market from the append-only odds firehose, with steam-move and line-drive detection.

Reads the odds archive table. Rows grouped by (market, bookmaker) then by selection; the steam move = >=5% implied-probability shift across snapshots (n>=3), line_drive = >=60% of consecutive moves in the same direction (n>=2). `juice` is the overround of the capture batch (sum of the batch's implied probabilities minus 1), so it is null where fewer than two priced outcomes share a captured_at, or on lay markets. Reads the archive's own column names (`outcome`/`price`/`point`) and serves them as `selection`/`odds`/`line`. Uses the standard auth guard/v1Success helper (newer pattern) rather than the older per-route boilerplate.

Query parameters
NameTypeRequiredDefaultDescription
event_idstringYes–Event identifier. Accepts the bare hex id (e467621918b702d29d87d82e2c464628) and the sport-key-prefixed form (basketball_nbl_e467621918b702d29d87d82e2c464628); a known <sport_key>_ prefix is stripped before the odds archive lookup. 400 error if missing.
marketstringNo–Market filter, e.g. "h2h", "spreads", "totals".
bookmakerstringNo–Filter to a single bookmaker.
fromstring (YYYY-MM-DD)No–Start date filter on captured_at. Clamped forward to the key's historicalDays entitlement and to a 90-day maximum window; the effective start is returned in meta.from.
tostring (YYYY-MM-DD)No–End date filter on captured_at (queried as to+'T23:59:59').
limitintegerNo100Max snapshots per outcome group, clamped 1-500.
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/odds/movement?event_id=evt_abc123"
Example response
{
  "success": true,
  "data": [
    {
      "event_id": "e8f2a1",
      "sport_key": "rugbyleague_nrl",
      "home_team": "Penrith Panthers",
      "away_team": "Melbourne Storm",
      "market": "h2h",
      "outcomes": [
        {
          "selection": "Penrith Panthers",
          "snapshots": [
            {
              "timestamp": "2026-09-01T00:00:00Z",
              "odds": 1.65,
              "line": null,
              "implied_prob": 0.6061,
              "juice": null
            },
            {
              "timestamp": "2026-09-03T02:00:00Z",
              "odds": 1.58,
              "line": null,
              "implied_prob": 0.6329,
              "juice": null
            }
          ],
          "steam_move": false,
          "line_drive": true,
          "open_odds": 1.65,
          "close_odds": 1.58,
          "move_pct": -4.24
        }
      ],
      "detected_at": "2026-09-01T00:00:00Z",
      "bookmaker": "sportsbet"
    }
  ],
  "meta": {
    "count": 1,
    "tier": "free",
    "event_id": "e8f2a1",
    "market": null,
    "bookmaker": null,
    "from": null,
    "to": null,
    "limit": 100,
    "steam_moves_detected": 0,
    "line_drives_detected": 1,
    "timestamp": "2026-09-03T04:00:00.000Z",
    "rate_limit": {
      "limit": 100,
      "remaining": 999,
      "reset": "2026-10-01T00:00:00.000Z"
    }
  }
}
GET/api/v1/opportunity-historyAPI plan

Archived arb/+EV opportunities that have since expired (cleaned up after 24h).

Archive-tier endpoint (the credit cost=5, comment: 'archive endpoint (historical opportunities)'). Feature 'historical' gates it to the paid 'api' tier only. Reads the primary store the archived-opportunity store collection ordered by archivedAt desc.

Query parameters
NameTypeRequiredDefaultDescription
typestringNo–"arb" or "ev" only; any other value returns 400.
sport_keystringNo–Filter by sport key (lowercased).
sincestring (ISO date)No–Clamped by the key's historicalDays entitlement via clampHistoricalFrom().
limitintegerNo50Max rows. Capped at 50 on free tier, 2000 on api tier (though feature itself is api-only).
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/opportunity-history?type=value"
Example response
{
  "success": true,
  "data": [
    {
      "id": "arb-2026-09-02-x91k",
      "type": "arb",
      "sport_key": "basketball_nba",
      "event_id": "b7c3d9",
      "event_name": "Boston Celtics vs Denver Nuggets",
      "commence_time": "2026-09-02T00:10:00Z",
      "market_key": "h2h",
      "profit_pct": 2.14,
      "ev_pct": null,
      "stake": 100,
      "legs": [
        {
          "bookmaker": "Ladbrokes",
          "outcome": "Boston Celtics",
          "odds": 2.05
        },
        {
          "bookmaker": "TAB",
          "outcome": "Denver Nuggets",
          "odds": 2.15
        }
      ],
      "archived_at": "2026-09-02T00:12:00.000Z",
      "created_at": "2026-09-01T23:40:00.000Z"
    }
  ],
  "meta": {
    "count": 1,
    "tier": "api",
    "limit": 50,
    "requested_limit": 50,
    "type": null,
    "sport_key": null,
    "since": null,
    "note": "Records cleaned up after 24 hours",
    "timestamp": "2026-09-03T04:00:00.000Z",
    "rate_limit": {
      "limit": 200,
      "remaining": 4995,
      "reset": "2026-10-01T00:00:00.000Z"
    }
  }
}
GET/api/v1/steam-movesFree tier

Recently detected steam moves (sudden multi-book odds shortening/drifting) across sports.

Reads the primary store the steam-move store collection (distinct from the raw-archive-derived /api/v1/odds/movement, which computes steam detection on the fly from the raw odds archive). This route consumes pre-computed steam-move docs instead.

Query parameters
NameTypeRequiredDefaultDescription
sport_keystringNo–
event_idstringNo–
directionstringNo–Must be "shortening" or "drifting"; anything else is ignored (treated as null).
min_move_pctnumberNo0Filters rows whose movePct is below this threshold.
bookmakerstringNo–Matched defensively against bookmaker/book/bookmakers/books fields, none of which are reliably populated per in-code comment.
limitintegerNo50Capped at 50 on free tier, 1000 on api tier.
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/steam-moves?sport_key=aussierules_afl"
Example response
{
  "success": true,
  "data": [
    {
      "id": "steam-2026-09-03-nrl-001",
      "event_id": "e8f2a1",
      "event": "Penrith Panthers vs Melbourne Storm",
      "sport_key": "rugbyleague_nrl",
      "sport_title": "NRL",
      "outcome": "Penrith Panthers",
      "direction": "shortening",
      "old_odds": 1.75,
      "new_odds": 1.55,
      "move_pct": -11.43,
      "old_implied_prob": 0.5714,
      "new_implied_prob": 0.6452,
      "implied_prob_delta": 0.0738,
      "bookmaker_count": 6,
      "commence_time": "2026-09-04T09:30:00Z",
      "detected_at": "2026-09-03T03:40:00.000Z"
    }
  ],
  "meta": {
    "count": 1,
    "tier": "free",
    "limit": 50,
    "requested_limit": 50,
    "direction": null,
    "min_move_pct": null,
    "filters": {
      "sport_key": null,
      "event_id": null,
      "direction": null,
      "min_move_pct": null,
      "bookmaker": null
    },
    "timestamp": "2026-09-03T04:00:00.000Z",
    "rate_limit": {
      "limit": 50,
      "remaining": 999,
      "reset": "2026-10-01T00:00:00.000Z"
    }
  }
}

Other categories

Gameday8 endpoints

Per-event head-to-head odds, alternate lines, best prices across books, player props, live state and AI-generated summaries.

Opportunities7 endpoints

Krok's built-in scanners — arbitrage, positive EV, middles, low-holds, player props and same-game multi (SGM) picks, already devigged against a blended sharp baseline.

Racing23 endpoints

The full Australian racing stack — thoroughbred, harness and greyhound. Meetings and runner fields, form, sectionals, ratings, market movers, exchange arbs, tote pools and results.

Odds Feed16 endpoints

Raw per-bookmaker prices as scraped, before any analysis layer. `/scraped-odds/*` paths are aliases of the equivalent `/odds-feed/*` route.

Sports8 endpoints

Sport reference data, team form guides, league standings, injury reports and weather-impact analysis.

Tips & Predictions4 endpoints

AI-generated betting tips with confidence scores and historical accuracy tracking.

Insights1 endpoint

Ranked leaderboards built on top of the stat feeds — per-sport player leaders for a chosen stat, season and view.

Tennis5 endpoints

ATP/WTA rankings, upcoming fixtures, match results, Elo ratings and surface-specific stats.

Historical7 endpoints

Deep archives — player and team game logs, shot charts, AFL/NRL historical data. Paid API plan only.

Reference7 endpoints

Static lookup data for building your own UI — players, venues, headshots, team logos and sport/league metadata.

Other Sports22 endpoints

Cricket, cycling, esports, Formula 1, golf, MMA, boxing, NFL and soccer coverage beyond the AU staples.

Infrastructure15 endpoints

Account and billing endpoints, bulk export, SSE streaming, webhook management and API health.

Prediction Markets3 endpoints

Polymarket and Kalshi sentiment plus a universal prediction-market catalogue and resolutions feed.