HomeBlog › What Data Format Do Odds APIs Return? A Guided Tour of a Live Odds Payload
API & Data

What Data Format Do Odds APIs Return? A Guided Tour of a Live Odds Payload

What Data Format Do Odds APIs Return? A Guided Tour of a Live Odds Payload

Fixtures, markets, prices: the shape almost every odds API returns, field by field — odds formats, IDs, versions, and the gotchas that break parsers.

What Data Format Do Odds APIs Return? A Guided Tour of a Live Odds Payload

Every odds API's documentation starts the same way — an endpoint, an auth header, and then a wall of JSON with no tour guide. This post is the tour guide. Once you've internalized the shape, every odds feed on the market looks familiar, because they nearly all return variations of the same three-level structure:

fixtures → markets → prices

A fixture is the event (Arsenal vs Chelsea, Tuesday 19:00 UTC). A market is a question about it (who wins? over/under 2.5 goals?). A price is one answer with odds attached (over 2.5 at 1.952). Everything else is metadata hanging off those three levels.

An annotated payload

Here's a trimmed live-soccer response in the shape we return — our names for the three levels are events → periods → markets, but it's the same structure (verify against the live docs before you parse; a blog post is not a schema):

{
  "sport_id": 1,
  "sport_name": "Soccer",
  "last": 141,
  "events": [
    {
      "event_id": 1602214470,        // stable event ID — your join key everywhere
      "league_name": "England - Premier League",
      "starts": "2026-07-08T19:00:00Z",   // ISO 8601, ALWAYS UTC
      "home": "Arsenal",
      "away": "Chelsea",
      "event_type": "live",          // "live" | "prematch" — same envelope for both
      "is_have_odds": true,
      "last": 1776430365,            // version counter — bumps on every change
      "periods": {
        "num_0": {                   // full match; num_1 = first half, and so on
          "money_line": { "home": 2.35, "draw": 3.40, "away": 3.05 },
          "totals": {
            "2.5": { "points": 2.5, "over": 1.952, "under": 1.909, "max": 500 }
          },
          "spreads": {
            "-0.5": { "hdp": -0.5, "home": 2.06, "away": 1.82, "max": 500 }
          }
        }
      }
    }
  ]
}

Six things in there account for ninety percent of parsing bugs. Let's take them in order of how often they hurt people.

1. Odds format: decimal is the default, and the safest

APIs speak decimal (2.35), American (+135), or fractional (27/20). Decimal has won among data APIs because it's the one you can do math on directly: implied probability is just 1/odds. If a feed offers a format parameter, take decimal and convert for display only — never store American odds and do arithmetic on them later; the sign discontinuity around ±100 is a bug farm.

2. IDs are your join keys — never match on names

Team and league names are display strings: they vary by feed, language, and time ("Man Utd" today, "Manchester United" tomorrow). The event_id is the contract. Key every internal structure on it, and note the detail in the payload above: the same fixture carries its ID from prematch into live (only event_type flips), so nothing re-keys at kickoff.

3. line belongs to the market, not the price

For totals and handicaps, the odds are meaningless without the line — over at 1.952 of what? That's why, in the payload above, totals and spreads are objects keyed by the line itself ("2.5", "-0.5"), with the line repeated inside each entry (points, hdp). When the line moves (2.5 → 2.75), a new market appears under a new key — it's not a price change on the old one. Parsers that key totals without the line silently mix prices from different questions. This is the single most common odds-data bug we see.

4. Timestamps and version counters

Two different jobs in the payload: starts says when the fixture kicks off (ISO 8601, UTC — convert at the display layer only), and last says how current this state is — a monotonic version counter that bumps on every change. It's what makes incremental polling work (ask for "everything since version X") and what makes stale or duplicate state detectable: ignore anything whose last is ≤ the version you already applied. If you're measuring anything time-sensitive (latency, follow-lag), stamp arrival time with your own clock; a producer-side field alone can't measure transit.

5. Snapshots vs deltas — the REST/stream divide

A REST response is a snapshot: complete state, self-contained, nothing to maintain. Streams (SSE/WebSocket) send a snapshot on connect and then deltas — add/update/delete records for the bits that changed. Your job becomes maintaining local state by applying deltas in seq order, and resyncing with a fresh snapshot after any disconnect. It's a few dozen lines and it's the entire price of admission to push delivery — the WebSocket guide walks through a working client.

6. The gotchas that break parsers at 2 a.m.

Takeaway

fixtures → markets → prices, decimal odds, IDs as keys, lines attached to markets, UTC everywhere, sequence numbers for ordering, and null-tolerant parsing for live play. Internalize that list and any odds API — ours or a competitor's — is an afternoon's integration instead of a week's archaeology. Then go make your first live call and see the shape for real.

FAQ

What format do odds APIs return data in? JSON, almost universally, structured as fixtures containing markets containing prices, with decimal odds as the standard among data-focused feeds.

What's the difference between decimal and American odds in an API? Same information, different encoding — but decimal supports direct arithmetic (1/odds = implied probability), so store decimal and convert only for display.

Why did my totals parser mix up prices? Almost certainly keying on market type without the line — over 2.5 and over 2.75 are different markets, and the line lives at the market level.

Do odds APIs use local time? Reputable ones are UTC-only (ISO 8601). If you ever see a bare timestamp with no zone, treat that feed with suspicion generally.

Get real-time Pinnacle odds in your code

Live & prematch markets with sub-second odds-drop alerts. Free trial key in seconds — no card.

Start free trial