v1 API ← Back to app

Edge Model Public API

Read-only access to championship probabilities, standings, and model-vs-market divergence. All endpoints require a Bearer token.

Base URL: https://www.edgemodel.tech

Introduction

The Edge Model API provides programmatic access to the same Bayesian predictions shown in the web app. Data is updated automatically as match results are recorded — typically within minutes of a final whistle.

API keys are issued by the Edge Model team. Contact support@edgemodel.tech to request access.

Authentication

Pass your API key in the Authorization header on every request:

Authorization: Bearer em_your_key_here

Example with curl:

curl https://www.edgemodel.tech/api/v1/presets \
  -H "Authorization: Bearer em_your_key_here"

Example with Python:

import requests

headers = {"Authorization": "Bearer em_your_key_here"}
r = requests.get("https://www.edgemodel.tech/api/v1/presets", headers=headers)
print(r.json())

Rate limits

60 requests per minute per API key. Exceeding the limit returns HTTP 429. The limit resets every 60 seconds.

Header (on 429)Meaning
Retry-AfterNot currently set — wait 60 s and retry

Error format

All errors return JSON with an error field:

{"error": "No saved state for preset 'epl-2026-27' — check /api/v1/presets for valid ids"}
StatusMeaning
401Missing or invalid API key
404Preset not found or no saved state for that preset
429Rate limit exceeded

List presets

GET /api/v1/presets Bearer required

Returns all active competition presets — league and tournament — with their metadata. Use the id field in subsequent calls to /api/v1/league/{id}/state and /api/v1/league/{id}/edge.

Example response

{
  "presets": [
    {
      "id":          "epl-2026-27",
      "name":        "Premier League 2026-27",
      "description": "Premier League · 20 clubs · 2026-27",
      "icon":        "🏴󠁧󠁢󠁥󠁮󠁧󠁿",
      "n_teams":     20,
      "format":      "league",
      "sport":       "soccer",
      "has_state":   true
    },
    ...
  ]
}
FieldTypeDescription
idstringPreset identifier — use this in other endpoints
namestringHuman-readable competition name
format"league" | "tournament"Competition type
sportstringSport (e.g. "soccer", "basketball_nba")
has_statebooleanWhether results have been recorded and a state exists

League state

GET /api/v1/league/{id}/state Bearer required

Returns the full league state for a preset: standings, Bayesian parameter posteriors, championship probabilities, and result history.

Replace {id} with a preset id from /api/v1/presets — e.g. /api/v1/league/epl-2026-27/state.

Example request

curl "https://www.edgemodel.tech/api/v1/league/epl-2026-27/state" \
  -H "Authorization: Bearer em_your_key_here"

Example response

{
  "preset_id": "epl-2026-27",
  "meta": {
    "id":             "epl-2026-27",
    "name":           "Premier League 2026-27",
    "n_teams":        20,
    "rounds":         2,
    "total_matches":  380,
    "matches_played": 47,
    "scoring":        {"win": 3, "draw": 1, "loss": 0}
  },
  "teams": [
    {
      "name":          "Arsenal",
      "played":        13,
      "wins":          9,
      "draws":         2,
      "losses":        2,
      "points":        29,
      "gf":            28,
      "ga":            14,
      "gd":            14,
      "attack_mean":   1.92,
      "defense_mean":  0.87
    },
    ...
  ],
  "history": [
    "Arsenal|2-1|Chelsea",
    "Man City|0-0|Liverpool",
    ...
  ]
}
FieldTypeDescription
teams[].namestringTeam name as used in the preset
teams[].pointsintLeague table points
teams[].gdintGoal difference
teams[].attack_meanfloatPosterior mean attack rate (goals/game)
teams[].defense_meanfloatPosterior mean conceding rate (goals/game)
history[]string[]Results in Home|score-score|Away format

Model-vs-market divergence

GET /api/v1/league/{id}/edge Bearer required

Returns unplayed fixtures where the model's win probability diverges from market-implied probability by at least the given threshold. Only fixtures with available market odds are included.

Query parameters

ParamDefaultDescription
threshold0.05Minimum edge (absolute probability difference) to include. Range 0–1.

Example request

curl "https://www.edgemodel.tech/api/v1/league/epl-2026-27/edge?threshold=0.08" \
  -H "Authorization: Bearer em_your_key_here"

Example response

{
  "preset_id":     "epl-2026-27",
  "threshold":     0.08,
  "odds_available": true,
  "fixtures": [
    {
      "home":          "Arsenal",
      "away":          "Chelsea",
      "commence_time": "2026-09-15T19:45:00Z",
      "model":  {"home": 0.5431, "draw": 0.2341, "away": 0.2228},
      "market": {
        "home": {"implied_prob": 0.4521, "odds": 2.21},
        "draw": {"implied_prob": 0.2688, "odds": 3.72},
        "away": {"implied_prob": 0.2791, "odds": 3.58}
      },
      "edge": {"home": 0.091, "away": -0.0563}
    }
  ]
}
FieldDescription
odds_availableFalse if The Odds API key is absent or the competition has no market data
model.home/draw/awayModel probability for each outcome (sums to ~1)
market.home.implied_probVig-adjusted implied probability from best available decimal odds
market.home.oddsBest decimal odds across tracked bookmakers
edge.homemodel.home − market.home.implied_prob (positive = model more bullish on home win)
Note: A positive edge means the model assigns higher probability than the market. This is informational — Edge Model is not a betting tool and does not recommend wagers.

Create API key (admin)

POST /api/v1/keys Admin session required

Generates a new API key. Requires an active admin session (not a Bearer key — admin login via the web app). Keys are not stored in plaintext after creation.

Request body

{"label": "My integration"}

Response

{"ok": true, "key": "em_a1b2c3d4...", "label": "My integration"}
Save the key immediately — it is returned once and cannot be retrieved again. To rotate a key, create a new one and delete the old entry from the key store on the server.

List API keys (admin)

GET /api/v1/keys Admin session required

Lists all issued API keys with their labels and creation dates. Requires an active admin session.

Response

{
  "keys": [
    {
      "key":     "em_a1b2c3d4...",
      "label":   "My integration",
      "created": "2026-09-03T10:00:00Z"
    }
  ],
  "count": 1
}