Endpoint

Event odds

Grouped decimal odds for one event across markets and bookmakers. Upstream bookmaker payloads are normalised into events, markets, outcomes, quote status, and observation timestamps.

GET/api/v1/events/{eventId}/oddsAuth: Required

Read grouped odds for one event across markets and bookmakers.

Query / path parameters

eventIdrequired
Numeric event id returned by /api/v1/events. Non-numeric ids return 400 validation_failed.
bookmaker
Optional comma-separated bookmaker slug filter. Blank or duplicate entries return 400 validation_failed.
transport
Product channel: rest (default) or live. Live requires plan entitlement; otherwise returns 403 live_not_enabled.
Request
curl "https://api.betspread.io/api/v1/events/12345/odds?bookmaker=tipico&transport=rest" \
  -H "Authorization: Bearer $BETSPREAD_API_KEY"
Response
{
  "data": {
    "event": {
      "id": "12345",
      "sport": "football",
      "leagueKey": "bundesliga",
      "leagueName": "Bundesliga",
      "homeTeam": "Borussia Dortmund",
      "awayTeam": "Bayern Munich",
      "kickoffAt": "2026-05-09T16:30:00.000Z",
      "marketCount": 1
    },
    "markets": [
      {
        "type": "match_result_1x2",
        "line": null,
        "bookmakers": [
          {
            "slug": "tipico",
            "displayName": "Tipico",
            "outcomes": [
              {
                "outcome": "home",
                "transport": "rest",
                "odds": 2.42,
                "status": "open",
                "lastUpdatedAt": "2026-05-04T12:10:14.000Z"
              }
            ]
          }
        ]
      }
    ]
  }
}

Response schema

Odds are returned as decimal odds. The grouped event odds payload uses odds inside each outcome; the flat OpenAPI quote schema uses oddsDecimal.

GET /api/v1/events/{eventId}/odds
{
  "data": {
    "event": {
      "id": "12345",
      "sport": "football",
      "leagueKey": "bundesliga",
      "leagueName": "Bundesliga",
      "homeTeam": "Borussia Dortmund",
      "awayTeam": "Bayern Munich",
      "kickoffAt": "2026-05-09T16:30:00.000Z",
      "marketCount": 1
    },
    "markets": [
      {
        "type": "match_result_1x2",
        "line": null,
        "bookmakers": [
          {
            "slug": "tipico",
            "displayName": "Tipico",
            "outcomes": [
              {
                "outcome": "home",
                "transport": "rest",
                "odds": 2.42,
                "status": "open",
                "lastUpdatedAt": "2026-05-04T12:10:14.000Z"
              }
            ]
          }
        ]
      }
    ]
  }
}

Quote status

REST endpoints return only quotes that are currently tradable: quote status open, observed within the last 24 hours, from product-eligible bookmakers. Suspended or closed quotes are omitted from REST responses, so the status field in REST payloads is always "open". Do not infer suspension from REST: a quote disappearing from a REST response means "no longer tradable or no longer fresh", nothing more.

Clients that need suspension awareness must consume the live stream, which carries quote status transitions in real time. Suspension signals depend on what each bookmaker's feed exposes; for sources without status semantics, quotes are emitted as open and age out of REST responses via the 24-hour freshness window.

Example

Each outcome ships with a lastUpdatedAt ISO-8601 timestamp from the source observation. See Quote freshness for how to handle stale outcomes on the client.