---
title: "List covered games"
method: GET
path: "/api/v1/games"
tags: ["Games"]
---

# List covered games

`GET /api/v1/games`

One coherent game view per row: both sides with their provider ids and live scores, the UTC kickoff, the provider's own status, the esports series format, and every linked Polymarket market with its condition id and outcome token ids. Built from the same provider-first live and upcoming projections the site's sports boards use, so a request pays no provider fan-out of its own. Ordered by kickoff, then by event_slug; games whose kickoff the provider has not published sort last. coverage names the sports and leagues this deployment serves and any scope whose source was unavailable for the read, so an empty page is never ambiguous. A sport or status outside the published vocabulary returns an empty page rather than a 400. Carries the board's existing competitor-bound provider moneyline price state by default, with an observation clock and explicit incomplete or invalid state. It does not fetch another provider endpoint. Sharp-money splits and holder identities remain on their own gated routes.

## Query parameters

- `sport` string
- `league` string
- `status` 'scheduled' | 'live' | 'paused' | 'ended' | 'postponed' | 'cancelled' | 'suspended' | 'delayed' | 'unknown'
- `starts_after` string, date-time
- `starts_before` string, date-time
- `limit` integer
- `cursor` string

## Headers

- `X-Query-Validation` 'strict'
- `If-None-Match` string

## Response `200`

A page of covered games with the deployment's published coverage

- object
  - `object` 'list', required
  - `data` Game[], required
    - `object` 'game', required
    - `event_slug` string, required — The game's identity, for example mlb-mil-cin-2026-06-22. The same key the live_sports_updated webhook pulse carries and the same key /api/v1/games/{event_slug} takes.
    - `game_id` string — The provider's Gamma gameId, as a string. Omitted when the canonical owner has no single value for this slug: the provider stamps one gameId across an event's derivative siblings, so an ambiguous read is reported as unknown rather than guessed.
    - `sport` string — The canonical sport bucket, for example Soccer or Table Tennis. Omitted when neither the board scope nor the provider category names one.
    - `league` string — The league tag, for example nfl or epl. Omitted for a sport served as one whole bucket with no league scope.
    - `title` string — The provider's event title. Omitted when the provider sent none.
    - `scheduled_at` string, date-time — Kickoff in UTC, as the provider supplied it. Omitted when the provider published none; coverage.schedule then reads unavailable.
    - `status` GameStatus, required — Where the game is in its own life, as the provider reports it. A postponement, a cancellation and a suspension each keep their own state, so a client can tell a game that will be played later from one that never will be.
      - `state` 'scheduled' | 'live' | 'paused' | 'ended' | 'postponed' | 'cancelled' | 'suspended' | 'delayed' | 'unknown', required — scheduled: kickoff is ahead or the provider still calls it scheduled. live: the provider reports it in play. paused: halftime or a provider-reported break. ended: the provider reported a final, an award or a forfeit. postponed, cancelled, suspended, delayed: the provider's own verdict, kept distinct. unknown: no provider state reached this read. A kickoff in the past is never read as live on its own.
      - `match_status` 'scheduled' | 'in_progress' | 'halftime' | 'penalty_shootout' | 'delayed' | 'suspended' | 'final' | 'final_overtime' | 'final_shootout' | 'awarded' | 'forfeit' | 'not_necessary' | 'postponed' | 'cancelled' | 'unknown' — The provider status folded onto one vocabulary across leagues. unknown means the provider sent a value this API has no meaning for; provider_status keeps that value verbatim. Omitted when no live-score frame carries a status.
      - `provider_status` string — The provider's status string, verbatim. Omitted when the provider sent none.
      - `period` string — The provider's period label, for example Q3, End Q2 or T5. Omitted when the provider sent none.
      - `clock` string — The game clock as the provider spells it, never reformatted. Omitted when the provider sent none.
      - `live` boolean — The provider's own in-play flag. Omitted when no live-score frame exists, which is not the same as false.
      - `ended` boolean, required — Whether the game is over. Always present.
    - `competitors` GameCompetitor[], required — Both sides, in the provider's own order. For a team league the provider lists the home side first. Empty when the provider identified neither side.
      - `name` string, required — The competitor's name as the provider gives it.
      - `provider_id` string — The provider's league-scoped competitor id, as a string. Omitted when the provider has not identified this side; coverage.competitors then reads labels.
      - `logo` string — Provider crest or logo URL. Omitted when there is none.
      - `score` string — The provider's score for this side, verbatim. A string because the provider sends one: a set score, a map score and a run total are not all integers. Omitted when no live-score frame carries a score.
      - `record` string — The provider's season record for this side, for example 12-4. Omitted when the provider sent none.
    - `series_format` string — The esports series length, for example Bo3. Omitted for everything else.
    - `draw_offered` boolean, required — Whether one of this game's markets pays on a draw. Read this instead of assuming a two-outcome moneyline.
    - `markets` GameMarket[], required — Every market this read linked to the game, ordered by condition_id.
      - `id` string, required — The mkt_-prefixed market id every other V1 response uses.
      - `condition_id` string, required — The raw provider condition id.
      - `platform` string, required — Always polymarket.
      - `slug` string — The provider's market slug. Omitted when the provider sent none.
      - `sports_market_type` string — The provider's own market type, for example moneyline or spread. Omitted when the provider sent none. Not an enum: the provider owns this vocabulary and adds to it.
      - `side` 'home' | 'away' | 'draw' | 'other' — Which side of the game this market's YES leg pays. draw is a real value: a 1X2 market's third leg is not a competitor. Omitted when the provider ids do not classify the leg, which is not the same as other.
      - `outcome_yes` string — The provider's label for the YES outcome. Omitted when the provider sent none.
      - `outcome_no` string — The provider's label for the NO outcome. Omitted when the provider sent none.
      - `outcome_token_ids` string[] — Polymarket CLOB token ids in the provider's own outcome-index order. Omitted when the provider has published none for this market.
      - `prices` GameMarketPrices — Provider-owned moneyline state with the observation clock that can be compared with game freshness.
        - `provider` union, required
          - GameMarketPricePaired — A validated provider moneyline pair bound to the two competitors.
            - `state` 'paired', required
            - `competitor_a` GameMarketPriceCompetitor, required — One competitor-bound provider moneyline price. No YES/NO inference is required.
              - …
            - `competitor_b` GameMarketPriceCompetitor, required — One competitor-bound provider moneyline price. No YES/NO inference is required.
              - …
            - `competitor_a_is_yes` boolean, required — Whether competitor A is the provider YES leg.
            - `binding_provenance` 'provider_ids' | 'exact_labels' | 'containment_labels' | 'elimination', required — How the existing sports-board writer bound prices to competitors.
          - GameMarketPriceIncomplete — The provider moneyline pair is incomplete; no numeric pair is invented.
            - `state` 'incomplete', required
            - `reason` 'outcome_prices_missing' | 'outcome_price_leg_missing' | 'zero_price_sentinel' | 'display_price_pair_unavailable' | 'outcome_identity_unavailable' | 'final_score_unavailable', required
            - `competitor_a_is_yes` boolean — Whether competitor A is the provider YES leg.
            - `competitor_a_provider_id` integer — The provider competitor id when identity is available.
            - `competitor_b_provider_id` integer — The provider competitor id when identity is available.
            - `binding_provenance` 'provider_ids' | 'exact_labels' | 'containment_labels' | 'elimination' — How the existing sports-board writer bound prices to competitors.
          - GameMarketPriceInvalid — The provider moneyline pair is invalid; no numeric pair is invented.
            - `state` 'invalid', required
            - `reason` 'team_cardinality' | 'outcome_cardinality' | 'price_cardinality' | 'non_finite_price' | 'out_of_range_price' | 'non_complementary_prices' | 'ambiguous_identity' | 'final_identity_mismatch', required
            - `competitor_a_is_yes` boolean — Whether competitor A is the provider YES leg.
            - `competitor_a_provider_id` integer — The provider competitor id when identity is available.
            - `competitor_b_provider_id` integer — The provider competitor id when identity is available.
            - `binding_provenance` 'provider_ids' | 'exact_labels' | 'containment_labels' | 'elimination' — How the existing sports-board writer bound prices to competitors.
        - `observed_at` string, date-time, nullable, required — Board cache vintage for Gamma or the older CLOB leg clock. Null when no reliable clock is available; never a Gamma-authored timestamp.
        - `observation_source` 'board_snapshot' | 'clob_display', required — The clock used for observed_at. board_snapshot is this service’s cache observation, not a provider source timestamp.
    - `freshness` GameFreshness, required — How current this game's facts are. Independent per source: the board half that produced the game, and the live-score frame that produced its scores.
      - `source` 'live' | 'upcoming', required — Which board half produced this game.
      - `source_status` 'ok' | 'unavailable', required — Whether that half returned a truthful source body for this read.
      - `source_availability` 'available' | 'unavailable' | 'not_applicable', required — Whether that half had a source body at all. not_applicable means the sport has no configured source for that half.
      - `source_freshness` 'fresh' | 'stale' | 'unknown' | 'not_applicable', required — Freshness of the cached source body, never inferred from the response clock or the row count.
      - `source_observed_at` string, date-time — The source body's data vintage. Omitted when the read has no vintage anchor, which is not age zero.
      - `source_age_seconds` integer — Age of source_observed_at in seconds, capped at 600. Omitted past the cap or with no anchor.
      - `delayed` boolean, required — Whether a reader should be told these rows are behind. This applies the half's own servable-age bar (15 s live, 120 s upcoming), which is not the same as source_freshness: a live board whose scores are seconds old reads stale for about half of every publish cycle and is not delayed.
      - `scores_observed_at` string, date-time — When this game's live-score frame was observed. Omitted when there is no frame.
      - `scores_source_at` string, date-time — The provider's own frame clock. Omitted when the frame carries none.
    - `coverage` GameCoverage, required — What this game's read actually supplied, so a client branches on coverage instead of on a missing key.
      - `scores` 'available' | 'unavailable', required — available when a live-score frame supplied this game's scores.
      - `competitors` 'provider_ids' | 'labels' | 'unavailable', required — provider_ids when every side carries a provider id, labels when only the provider's names identify them, unavailable when neither exists. Do not join on names when this reads labels.
      - `schedule` 'available' | 'unavailable', required — available when the provider supplied a kickoff.
    - `url` string, required — The game's page on 0xinsider.
  - `has_more` boolean, required
  - `next_cursor` string — Pass as cursor for the next page. Present only when has_more is true.
  - `as_of` string, date-time, required — When this read assembled the catalog. Per-source vintage is on each game's freshness.
  - `coverage` GamesCoverage, required — What this deployment covers, published with every page so a client never has to guess whether an empty list means no games or no coverage.
    - `sports` string[], required — Canonical sport buckets served, sorted.
    - `leagues` string[], required — League tags served, sorted.
    - `sources_unavailable` string[], required — Scopes whose source half was unavailable for this read, as <sport>:<half>. Empty means every scope answered.
  - `meta` ResponseMeta, required
    - `request_id` string, required — Unique request ID (req_ prefix). The same value as the X-Request-Id response header, the request's usage accounting row and its log lines.
    - `cached` boolean, required
    - `cache_age_s` integer — Cache age in seconds. Omitted when the response was not cached, and also when it was cached but its age cannot be established (an entry stored before its cache carried a computed instant). Never a placeholder: an unknown age is reported as no value rather than as the cache TTL.
    - `cost` integer, required — Advisory request weight (relative compute cost). 1 for simple reads; higher for heavier endpoints. Not a credit/price.
    - `ranking_generation` integer — Committed PostgreSQL-owned leaderboard generation for the returned rows and cursor. Present on GET /api/v1/leaderboard; omitted on endpoints that do not read this ranking.
    - `ranking_as_of` string, date-time — Authoritative RFC3339 timestamp from cache_generations.updated_at for ranking_generation. It is read in the same repeatable-read snapshot as the leaderboard rows and is not request time, cache write time, or row insertion order.
    - `directional_source` 'live' | 'degraded' — Which path produced the team-directional read on this response. Only present on endpoints that compute one (today: GET /api/v1/sports-edge-signals). "live" means the read RAN. "degraded" means it FAILED, so nothing was measured and the ranking fell back to raw conviction. The flag describes the READ, not its consequence: a read that ran and found nothing groupable also leaves the directional fields null, and that is honestly "live" -- the per-signal nulls already say "nothing to enrich here", so this snapshot-level flag carries only what they cannot, namely whether the read ran at all. A degraded response is cached on the shorter degraded TTL so it self-heals. Reported SEPARATELY from ranking_source because the two degradations are independent -- a sharp-money DB miss weakens the ranking DATA, a directional failure removes a ranking WEIGHT -- and a consumer down-weighting a degraded response needs to know which input it lost. Omitted on endpoints that compute no directional read.
    - `ranking_source` 'live' | 'db_only' — Which ranking-data path produced this response. Only present on endpoints that can degrade a ranking (today: GET /api/v1/sports-edge-signals). "live" is the normal path (the current holder pile from the provider batch); "db_only" is the degraded fallback (a truthful but weaker trader_markets ranking) served when the live sharp-money ranking batch is unavailable (a sharp-money DB read failure, not a Polymarket outage) and cached on a shorter TTL, so a consumer can down-weight or skip it. Omitted on endpoints that never degrade.
    - `category_skill_source` 'live' | 'partial' | 'degraded' | 'unavailable' — Whole filtered snapshot category-evidence status before pagination. Operational live always remains partial source coverage.
    - `category_skill_model_version` string
    - `category_skill_taxonomy_version` string
    - `category_skill_platform` 'polymarket'
    - `category_skill_scope` 'observed_goldsky_primary_taker_fill'
    - `category_skill_source_coverage` 'partial_whale_threshold_fills' | 'graded_wallet_fills'
    - `category_skill_observation_started_at` string, date-time
    - `category_skill_model_operationally_degraded` boolean — Whole-model operational readiness captured with the category model snapshot. Present on category-enriched responses even when the filtered signal list is empty. When true, category_skill_source is degraded and sports-edge-signals uses the shorter degraded cache TTL.
    - `category_skill_status_counts` object
      - `live` integer, required
      - `insufficient` integer, required
      - `stale` integer, required
      - `unknown` integer, required
      - `degraded` integer, required
    - `category_skill_base_payload_hash` string — SHA-256 of the funded signal membership/order/rank/cursor vector immediately before category-skill enrichment. Sports-edge-signals only.
    - `category_skill_enriched_base_payload_hash` string — Independent SHA-256 recomputation over the same base fields immediately after category-skill enrichment. Equality with category_skill_base_payload_hash proves shadow enrichment did not change funded inputs. Sports-edge-signals only.

## Other responses

- `304` — Not Modified. Returned when If-None-Match matches the current payload.
- `400` — Bad request. error.param names the parameter: limit outside 1-100 or not an integer, starts_after or starts_before that is not an RFC 3339 instant, starts_after later than starts_before, or a cursor this endpoint did not issue. An unknown sport or status is not a 400; it returns an empty page.
- `401` — Missing or invalid API key
- `402` — Active Pro subscription required. The key is valid but the account has no active Pro subscription; error.reason is subscription_inactive and error.message names the reactivation URL (https://0xinsider.com/billing). Permanent until a person reactivates: no Retry-After, never retry on a schedule.
- `403` — Account access denied
- `408` — The handler did not answer inside the server's 30-second timeout. error.code is request_timeout. On GET and HEAD the response carries Retry-After and error.retry_at; on a mutation it carries neither, because the request may have completed on the server: check its state before repeating it, and reuse its Idempotency-Key.
- `423` — Account is locked
- `429` — Rate limit exceeded. Three independent budgets. (1) 100 requests/minute per user (sliding window), on every authenticated route. (2) On the BATCH routes only: 2500 batch item units/minute per user, reserved before any item is executed. A batch with N requested items costs N item units, including duplicate and invalid items. 2500 = 100 requests x 25 items per batch, which is the most item work a key can buy through the request limiter at all: a caller may spend their entire 100-request minute on full 25-item batches without the item budget being what stops them. The REQUEST budget is the effective ceiling, and batching is never the more expensive choice. The item budget can still deny at a sliding-window boundary (both counters carry the previous window forward with a floor, and the item counter runs 25x the request counter), so honor a 429 from either. Over-quota batches return 429 with Retry-After plus RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset before any item work is done. (3) The monthly quota: Pro includes 250,000 authenticated requests per UTC calendar month, whatever the billing cadence. Over 250,000: with pay as you go on, requests keep answering and the excess bills at USD 0.20 per 1,000 on a monthly invoice, up to 1,000,000 requests a month; without it, from October 1, 2026, the next request answers 429 rate_limited with error.reason monthly_quota_exceeded and a Retry-After to the month's reset, and from the same day a pay-as-you-go account answers the same past 1,000,000. A refused request is not counted. Every authenticated response carries X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining, and X-Monthly-Quota-Reset (unix seconds, the first of next month). (4) The per-address budget: 1200 requests/minute per IP, shared by every caller behind one address and counted before authentication, on every route. A 429 from it carries error.reason ip_rate_limited and describes that bucket in RateLimit-*; a throttled address (sustained over-limit traffic) carries error.reason ip_throttled with a Retry-After of minutes to days, and a request before it does not shorten the cooldown. Every 429 is the standard error envelope with meta.request_id equal to X-Request-Id.
- `503` — Temporarily unavailable. error.reason=read_model_warming means the sports board supply did not answer this read; Retry-After is 5 seconds and the next read normally succeeds. The authenticated rate limiter being unavailable answers the same status with its own per-process cooldown.

## Changes

- **2026-09-23** `7e57bd9dc8b5` — 1 info
  - added the optional property `data/items/markets/items/prices` to the response with the `200` status
- **2026-09-23** `ece7a25b7a44` — 8 warning, 8 info
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `400`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `401`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `402`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `403`
  - …12 more
- **2026-09-23** `2325281a7d2a` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/0xinsider/apis/0xinsider-api/changes/api/v1/games/get.md)

---

[API](https://skmtc.dev/0xinsider/apis/0xinsider-api.md) · [All operations](https://skmtc.dev/0xinsider/apis/0xinsider-api/llms.txt) · [OpenAPI document](https://skmtc.dev/0xinsider/apis/0xinsider-api/revisions/2035b3316329?raw)
