Krok Odds

Infrastructure — Account, usage & bulk export

The account, usage & bulk export half of the Infrastructure reference — every route with its parameters, credit cost and a worked example.

5 of 15 endpoints · all categories · get a free API key

GET/api/v1/bulkAPI plan

Enterprise cursor-paginated JSON bulk export of the historical archive across 13 datasets (team/player game logs, prop results, game results, MLB/soccer/NCAAF/NFL/NHL/NRL advanced stats, exchange BSP/results). No ?dataset= returns the dataset manifest.

Tier detail: api (bulk_export is paid-only, not in the free-tier feature set)

the credit cost: 25 (enterprise-weighted, set explicitly in the standard v1 route factory config). Cache TTL 3600s both tiers (archive is immutable so cached hard). Cursor pagination via keyset pagination by id (`.order(id).gt(id, cursor).limit(n)`) — index-cheap and resumable. Companion CSV/JSON export at /api/v1/export shares the same bulk_export gate and 25-credit cost.

Query parameters
NameTypeRequiredDefaultDescription
datasetstringNo–One of: the team game-log store, the player game-log store, player_history, prop_results, game_results, mlb_advanced, soccer_xg, ncaaf_player_games, the NFL tracking store, nhl_skaters, nrl_player_games, exchange_bsp, exchange_results. Omitted → returns manifest (list of {dataset, description}) with no DB read.
sport_key | sportstringNo–Only supported for the player game-log store and nrl_player_games datasets; 400 otherwise (message points caller to /api/v1/historical/player-game-log).
cursorstringNo–Opaque id cursor for resumable pagination — pass back `next_cursor` from the previous response until it's null.
limitintegerNo100Row cap. Free tier max 100, api tier max 500 (though the feature itself is api-tier gated).
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/bulk?dataset=value"
Example response
{
  "success": true,
  "data": [
    {
      "id": "0001",
      "sportKey": "americanfootball_nfl",
      "team": "KC",
      "gameDate": "2026-08-30"
    }
  ],
  "meta": {
    "count": 100,
    "tier": "api",
    "limit": 100,
    "requested_limit": 100,
    "dataset": "team_game_logs",
    "collection": "team_game_log",
    "next_cursor": "0100",
    "has_more": true,
    "timestamp": "2026-09-03T00:00:00.000Z",
    "rate_limit": {
      "limit": 100,
      "remaining": 49975,
      "reset": "2026-10-01T00:00:00.000Z"
    }
  }
}
GET/api/v1/exportAPI plan

Enterprise bulk data export as downloadable CSV (or JSON) from the cold archive mirror — companion to the JSON-only /api/v1/bulk endpoint.

Tier detail: api (bulk_export is paid-only)

Uses the standard auth guard(request, 'bulk_export', 25) — same 25-credit weighting as /api/v1/bulk. Reads the Postgres archive by default (ordered by id, so the page is stable); the cold-archive mirror is used only when the cold-archive flag is on. 503 'Dataset not yet available' when the dataset's table is missing. CSV response sets filename `krok-{datasetKey}-{YYYY-MM-DD}.csv` and header X-Krok-Export-Rows with the actual row count. Cache 1800s for the json format variant.

Query parameters
NameTypeRequiredDefaultDescription
datasetstringYes–One of: game_results, player_props_results, model_track_record, gameday_odds_history, clv_archive, ev_hit_rates. 400 if missing/unknown.
limitintegerNo5000Capped at 5000 for both free and api tier (LIMIT_BY_TIER).
formatstringNocsvcsv (file download, Content-Disposition attachment) or json (standard v1 envelope via v1Success).
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/export?dataset=value"
Example response
{
  "success": true,
  "data": [
    {
      "id": "g1",
      "sport_key": "americanfootball_nfl",
      "home_score": 24,
      "away_score": 17,
      "completed": true
    }
  ],
  "meta": {
    "dataset": "game_results",
    "label": "Settled game results",
    "limit": 5000,
    "requested_limit": 5000
  }
}
GET/api/v1/meFree tier

API key introspection — returns the caller's tier, monthly usage/limit/remaining, per-request rate limit window, reset date, and a masked key preview.

Tier detail: free (no feature/tier gate at all — just requires a valid, active key)

CORRECTION vs. task brief: this route is API-KEY auth (X-API-Key header / apikey / api_key query param -> API-key verification), NOT dashboard session auth (dashboard-session auth) — it does not import server-auth at all. Only webhooks/route.ts and clv-archive/[eventId]/route.ts use session auth in this batch of 14 (clv-archive/[eventId] has since moved to API-key auth on 'closing_lines' — see its entry). PER_TIER_REQUEST_LIMITS here: free=100, api=10000 (note: api's 10000 differs from the 500-ish caps seen on most other free/api routes).

Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/me"
Example response
{
  "success": true,
  "data": {
    "tier": "free",
    "monthly_limit": 1000,
    "current_usage": 42,
    "remaining": 958,
    "usage_pct": 4.2,
    "reset_date": "2026-10-01T00:00:00.000Z",
    "per_request_limit": 100,
    "rate_limit_window": {
      "limit": 60,
      "remaining": 55,
      "reset": "2026-09-03T00:05:00.000Z"
    },
    "api_key_preview": "krok...ab12"
  },
  "meta": {
    "timestamp": "2026-09-03T00:00:00.000Z"
  }
}
GET/api/v1/me/usageFree tier

Credit and rate-limit usage for the calling key — tier, credits used/remaining/limit, usage percentage, the reset date and the live rate-limit window.

Tier detail: free (no feature/tier gate — only requires a valid, active key)

Measured 2026-10-22 against prod. Same counters as /api/v1/me but under different field names — `credits_used`/`credits_remaining`/`credits_limit` here vs `current_usage`/`remaining`/`monthly_limit` there; `rate_limit` here vs `rate_limit_window` there. /me additionally returns `api_key_preview` and `per_request_limit`. No `x-credits-cost` header (a read costs 1 credit). `Cache-Control: private, no-store`. Keyless → 401 `API key required`. Response headers carry the same numbers: `x-credits-limit`, `x-credits-remaining`, `x-credits-reset`, `x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset`, `x-ratelimit-tier`.

Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  "https://krokodds.com.au/api/v1/me/usage"
Example response
{
  "success": true,
  "data": {
    "tier": "api",
    "credits_used": 62240,
    "credits_remaining": 437760,
    "credits_limit": 500000,
    "usage_pct": 12.45,
    "reset_date": "2026-11-01T00:00:00.000Z",
    "rate_limit": {
      "limit": 500,
      "remaining": 462,
      "reset": "2026-10-22T07:58:00.000Z"
    }
  },
  "meta": {
    "truncated": false,
    "timestamp": "2026-10-22T07:57:25.241Z"
  }
}
GETPOSTDELETE/api/v1/webhooksFree tier

CRUD for outbound webhook subscriptions: GET lists the caller's subscriptions (secret never returned), POST registers a new one and answers its whsec_ signing secret once (max 10 per account), DELETE removes one by id.

Tier detail: all plans — webhooks is in the free-tier feature set. The route verifies the X-API-Key presented on the request (401 without one) and applies no tier gate.

API-key auth (X-API-Key header) — no key answers 401 {error:'API key required'}, an invalid one 401. No tier gate: 'webhooks' sits in the free-tier feature set, so free and api keys behave identically here (measured 2026-10-23: free key 200, api key 200, no key 401). GET reads `api_webhooks` (limit 500) and keeps rows whose keyHash or userId matches the caller, capped at 50, returning {success,data:[{id,url,events,active,created_at}],meta:{count,truncated}} — the secret is never in this response. POST validates url + a non-empty events array against the 14 accepted event names, runs the URL through checkWebhookUrl() (SSRF guard), refuses an 11th subscription ('Maximum 10 webhooks per account'), and upserts {userId,keyHash,url,events,label,active,secret,createdAt} into `api_webhooks`. DELETE requires ?id=, 404s when the row is missing, 403s when it belongs to another caller, then hard-deletes the row (supabaseDelete — not a deactivate). This route mints the signing secret too: POST stores whsec_<32-hex> on the row and returns it once in the create response, exactly as the dashboard route /api/api-keys/webhooks does; GET never returns it. Responses carry account-level X-Credits-* headers only — the route has no per-minute limiter — plus Cache-Control: private, no-store and CORS, with OPTIONS answering 204. The route does not consult the per-route tier cap map: `limit` is not a parameter and the list is fixed at 50.

Body (JSON)
NameTypeRequiredDefaultDescription
url (POST)stringYes–Destination HTTPS URL. Passed through checkWebhookUrl() SSRF guard (rejects internal/private-network targets) before being accepted.
events (POST)string[]Yes–Event types to subscribe to. Required and must be non-empty (400 'events array is required' otherwise); each value must be one of arb_created, snipe_created, middle_created, low_hold_created, steam_move_created, result.settled, racing.meeting.posted, racing.result.settled, racing.odds.movement, racing.betfair.update, sports.match.started, sports.result.settled, sports.odds.movement, sports.player.prop.update — anything else is 400.
label (POST)stringNo–Free-text label stored with the subscription.
id (DELETE)stringYes–Subscription id to remove. 404 if it does not exist; 403 if it belongs to someone else. The row is hard-deleted, not deactivated.
Example request
curl \
  -H "X-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url (POST)":"value","events (POST)":"evt_abc123","label (POST)":"value","id (DELETE)":"abc123"}' \
  "https://krokodds.com.au/api/v1/webhooks"
Example response
{
  "GET": {
    "success": true,
    "data": [
      {
        "id": "wh_1758700800000_ab12cd",
        "url": "https://example.com/hook",
        "events": [
          "arb_created",
          "middle_created"
        ],
        "active": true,
        "created_at": "2026-09-01T00:00:00.000Z"
      }
    ],
    "meta": {
      "count": 1,
      "truncated": false
    }
  },
  "POST": {
    "success": true,
    "data": {
      "id": "wh_1758700900000_ef34gh",
      "url": "https://example.com/hook2",
      "events": [
        "arb_created"
      ],
      "label": "",
      "active": true,
      "secret": "whsec_<32-hex>"
    }
  },
  "DELETE": {
    "success": true,
    "deleted": "wh_1758700900000_ef34gh"
  }
}

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.

Additional Data19 endpoints

Odds history, steam-move detection, player prop stats/results, injuries, weather and other supporting feeds.

Prediction Markets3 endpoints

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