Documentation

Quickstart

From zero to your first prediction response in under five minutes. You need an API key (contact the team to get one), a terminal, and any HTTP client.

Step 1: Get your API key

API keys are provisioned during onboarding. Once you have an account, find your key in the dashboard under Settings > API Keys. Keys look like:

Text
oxd_live_sk_a7b3c9d1e5f2g8h4i6j0k

Keep keys out of version control. Use environment variables or a secrets manager in production.

Step 2: Authenticate a request

Pass your API key in the X-OXD-Key header on every request. There is no session or OAuth flow.

cURL
curl -X GET \
  "https://api.onxyodds.com/v1/matchups?sport=basketball&date=2026-07-01" \
  -H "X-OXD-Key: oxd_live_sk_a7b3c9d1e5f2g8h4i6j0k" \
  -H "Accept: application/json"
Python
import requests

API_KEY = "oxd_live_sk_a7b3c9d1e5f2g8h4i6j0k"
BASE_URL = "https://api.onxyodds.com/v1"

headers = {
    "X-OXD-Key": API_KEY,
    "Accept": "application/json"
}

resp = requests.get(
    f"{BASE_URL}/matchups",
    headers=headers,
    params={"sport": "basketball", "date": "2026-07-01"}
)
data = resp.json()

Step 3: Fetch upcoming matchups

The /matchups endpoint returns a list of upcoming games for a given sport and date. Pass sport and date as query parameters.

Response JSON
{
  "data": [
    {
      "matchup_id": "mup_9kx7m3a",
      "sport": "basketball",
      "scheduled_at": "2026-07-01T20:00:00Z",
      "home_team": { "id": "team_042", "label": "Home Club" },
      "away_team": { "id": "team_071", "label": "Away Club" },
      "predictions_available": true
    }
  ],
  "meta": {
    "request_id": "req_0kd2p9n4",
    "count": 1,
    "generated_at": "2026-07-01T08:11:04Z"
  }
}

Step 4: Pull predictions for a matchup

Pass a matchup_id to /predictions to get the full win-probability breakdown, upset-risk rating, and model confidence bands.

Response JSON
{
  "data": {
    "matchup_id": "mup_9kx7m3a",
    "home_win_prob": 0.61,
    "away_win_prob": 0.39,
    "upset_risk": "moderate",
    "confidence": {
      "band": "medium-high",
      "home_range": [0.54, 0.68]
    },
    "model_version": "v4.1",
    "generated_at": "2026-07-01T08:11:07Z"
  }
}

Step 5: Fetch talking points

Talking points are structured headline-ready objects your CMS can render directly. Each has a type, a headline, supporting body copy, and editorial tags.

cURL
curl -X GET \
  "https://api.onxyodds.com/v1/talking-points?matchup_id=mup_9kx7m3a" \
  -H "X-OXD-Key: oxd_live_sk_a7b3c9d1e5f2g8h4i6j0k"
Response JSON
{
  "data": [
    {
      "type": "upset_alert",
      "headline": "Model flags moderate upset risk heading into tip-off",
      "body": "Away Club wins 39% of comparable matchups by model history, but recent form suggests a tighter contest than the opening line implies.",
      "tags": ["upset_risk", "pre_game"]
    },
    {
      "type": "confidence_band",
      "headline": "Home Club holds 61% win probability with medium-high model confidence",
      "body": "The model's 90th-percentile range sits between 54% and 68%, indicating a decided but not dominant edge heading into the game.",
      "tags": ["win_prob", "confidence", "pre_game"]
    }
  ],
  "meta": {
    "matchup_id": "mup_9kx7m3a",
    "count": 2
  }
}

Rate limits

All responses include rate-limit headers. Check them before making follow-up requests in loops or scheduled jobs:

Response headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 284
X-RateLimit-Reset: 1751410800

When you exceed your limit the API returns HTTP 429 with a Retry-After header in seconds. Back off and retry after the indicated delay.

Error handling

Errors follow a consistent shape. Always read error.code for machine-readable classification and error.message for a plain-text description.

Error response (401)
{
  "error": {
    "code": "auth_invalid_key",
    "message": "The API key provided is invalid or has been revoked.",
    "request_id": "req_0dk9s2x1"
  }
}

Common error codes:

  • auth_invalid_key - API key is missing, malformed, or revoked (401)
  • auth_quota_exceeded - Monthly quota exhausted (402)
  • not_found - Matchup ID or resource does not exist (404)
  • rate_limit_exceeded - Per-minute rate limit hit (429)
  • server_error - Transient server-side error, retry after a short delay (500)

Next steps

You have the core flow. From here: