Skip to main content
Returns the matches currently held in the book for one sport, as metadata only. This is the endpoint you use to discover match ids; prices come from GET /odds or the live stream.
Scope: odds · Sportsbook grant: pinnacle
Prices are deliberately not included here. markets is always null on this endpoint, no matter how many markets the match actually has. Listing the whole book with prices attached would be a large response that is stale the moment it is serialized.

Query parameters

sport is required. A match list is only useful per sport, and requiring it means one cached, gzipped response can be reused for every caller granted that sport. Call GET /sports first for the ids you hold.
Results are filtered by your key’s per-sport grants. With no sport filter — including ?league=<id> on its own — matches in ungranted sports are silently absent. With ?sport=<id> for a sport you do not hold, this endpoint returns 403 {"error": "API key not permitted for sport <id>"}. Match ids you discover here are always safe to pass to GET /odds and to WS /data subscribes.

Request

Fetch the whole book for a sport, including every derivative:

What the response contains

By default the response is scoped to what you almost certainly want:
  • Games — every top-level matchup for the sport.
  • Live derivative twins — when a fixture goes in-play the sportsbook mints a new matchup id for the live book and parents it to the prematch one. Those in-play children are always listed, because a parent-only filter would hide the entire live book. Each carries parent_id back to its prematch entry.
  • Parentless specials — a special with no parent (an outright, for example) is itself top-level and is always listed.
Every top-level entry carries specials_count and live_specials_count, so you can tell at a glance how many derivatives a game has and how many of them are currently in play. Pass ?include=specials to return the entire catalog — every derivative matchup, not just the in-play twins. On a busy card the difference is large (a live baseball sport goes from ~17 KiB by default to ~479 KiB with include=specials), so only opt in when you actually want to enumerate the whole book.

Response

A bare JSON array, sorted ascending by id. No matches held returns [].

Match object

Participant object

Specials

A special is a derivative market that the sportsbook models as its own matchup — player props, correct score, winning margin, odd/even, and similar. A parent game’s own book does not contain them; each derivative has its own id, its own participants, and its own markets. The split between a game and its derivatives is on parent_id, not on type. A child’s type varies by sport:
  • On baseball and most sports, derivatives are type:"special" with a special description.
  • On tennis, many derivatives are type:"matchup" carrying units:"Games" or units:"Sets" — around half of the tennis catalog in practice.
Both shapes are counted in specials_count, and both are included when you pass ?include=specials. To tell whether an entry is a derivative, check parent_id rather than type.

Reading a game and its derivatives

There are three ways to pull the derivatives for one game:
  1. Read specials_count and live_specials_count on the game in the default list, then follow up with GET /odds?match=<game>&include=specials to fetch the game’s own selections and every derivative’s selections in one call.
  2. Ask for the whole catalog with ?include=specials here, then filter by parent_id.
  3. Subscribe to the game on the live stream — subscribing to a game covers its derivatives too.

Caching, gzip, and ETag

Because this response is metadata rather than prices, it is safe to serve from a short-lived cache — and it is the only Passthrough endpoint that is cached.
  • Cache TTL. Responses are reused for up to PINNODDS_REST_CACHE_TTL (default 1 second) across every client granted that sport. Worst-case staleness is therefore one TTL, and only for fields like is_live, specials_count, and the match list itself. Prices never appear here, so the trade-off is bounded and safe.
  • Gzip. Responses above PINNODDS_REST_GZIP_MIN_BYTES (default 1 KiB) are compressed if you send Accept-Encoding: gzip. On a live baseball card this is a roughly 17× reduction — 212 KB raw to about 13 KB on the wire.
  • ETag. Every response carries an ETag header. Send it back on the next request as If-None-Match and the server answers 304 Not Modified with an empty body when the response would be identical.
Nothing that carries a price is cached: GET /odds and the WebSocket are always live.

Errors