SharpAPI Game State API

Live game state data (Game State add-on or Enterprise)

Business capability
Sports, Betting & Fantasy AE-180.80

Operations 2

GET /gamestate Live game state for every sport #
GET /gamestate/{sport} Live game state for a single sport #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/sharpapi:sharpapi-game-state-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

sharpapi-game-state-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Sharp Game State API
  version: 3.28.0
  description: Real-time sports betting odds API with +EV detection, arbitrage, middles, and low-hold opportunities.
  contact:
    name: SharpAPI Support
    url: https://sharpapi.io
    email: support@sharpapi.io
  license:
    name: Proprietary
    url: https://sharpapi.io/terms
  x-generated-at: '2026-10-13T20:02:34Z'
  x-commit-sha: 850f5cb
servers:
- url: https://api.sharpapi.io/api/v1
  description: Production
security:
- ApiKeyHeader: []
- BearerAuth: []
tags:
- name: Game State
  description: Live game state data (Game State add-on or Enterprise)
paths:
  /gamestate:
    get:
      operationId: listAllGameState
      summary: Live game state for every sport
      description: 'Returns aggregated live game state (scores, periods, clocks, situational data) for every sport with active events. Merged across sportsbooks with a consensus-based algorithm so a single misbehaving book can''t skew the result. Requires the **Game State add-on** ($79/mo, available on any paid plan) or the **Enterprise** tier. A fixture that has just finished stays here for 15 minutes after completion as a terminal row (`status: "final"`) — see the `status` / `is_live` parameters and the `EventGameState` schema.'
      tags:
      - Game State
      responses:
        '200':
          description: Live game state keyed by sport then event_id
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/DataEnvelope'
                - type: object
                  properties:
                    data:
                      type: object
                      description: Map of sport name to a map of event_id → EventGameState
                      additionalProperties:
                        type: object
                        additionalProperties:
                          $ref: '#/components/schemas/EventGameState'
              example:
                data:
                  soccer:
                    argentina_-_primera_division_bocajuniors_defensayjusticia_2026-04-23:
                      home_team: Defensa y Justicia
                      away_team: Boca Juniors
                      sport: soccer
                      league: argentina_-_primera_division
                      home_score: 0
                      away_score: 1
                      game_period: 2H
                      game_clock: '49:06'
                      is_live: true
                      possession: away
                      corners_home: 1
                      corners_away: 0
                      primary_book: draftkings
                      book_count: 6
                    montenegro_-_prva_liga_bokelj_otrantolympiculcinj_2026-04-23:
                      home_team: Bokelj
                      away_team: FK Otrant-Olympic Ulcinj
                      sport: soccer
                      league: montenegro_-_prva_liga
                      home_score: 2
                      away_score: 1
                      score_type: points
                      winner: home
                      status: final
                      completed_at: '2026-04-23T23:48:55Z'
                      is_live: false
                      stale: false
                  baseball:
                    mlb_redsox_yankees_2026-04-23:
                      home_team: New York Yankees
                      away_team: Boston Red Sox
                      sport: baseball
                      league: mlb
                      home_score: 2
                      away_score: 1
                      game_period: T5
                      is_live: true
                      primary_book: fliff
                      book_count: 9
                updated_at: '2026-04-23T23:55:01.234Z'
        '400':
          description: Unrecognised `status` or `is_live` value. The error body names the accepted set in `details.accepted`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: validation_error
                  message: 'is_live must be one of: true, false'
                  details:
                    parameter: is_live
                    accepted:
                    - 'true'
                    - 'false'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/TierRestricted'
      parameters:
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - final
          example: final
        description: Return only the carried terminal (finished) rows. `final` is the only accepted value — live rows are the default set, and `is_live=true` selects them alone. Case-insensitive. Any other value returns `400 validation_error` with `details.accepted` = `["final"]`.
      - name: is_live
        in: query
        required: false
        schema:
          type: string
          enum:
          - 'true'
          - 'false'
          example: 'true'
        description: '`true` returns live rows only, excluding every carried terminal row; `false` returns non-live rows only, which today means the carried terminal rows. Case-insensitive. Any other value — including `1` and `0` — returns `400 validation_error` with `details.accepted` = `["true","false"]`.'
  /gamestate/{sport}:
    get:
      operationId: getGameStateForSport
      summary: Live game state for a single sport
      description: 'Returns aggregated live game state for events in one sport. Response shape matches `GET /gamestate` but `data` contains a single key (the path `sport`). Unknown sports return an empty `data` object, never 404. Requires the **Game State add-on** ($79/mo, available on any paid plan) or the **Enterprise** tier. A fixture that has just finished stays here for 15 minutes after completion as a terminal row (`status: "final"`) — see the `status` / `is_live` parameters and the `EventGameState` schema.'
      tags:
      - Game State
      parameters:
      - name: sport
        in: path
        required: true
        schema:
          type: string
          example: soccer
        description: 'Atlas sport id. Case-insensitive. Known values: `baseball`, `basketball`, `football`, `hockey`, `soccer`, `tennis`, `table_tennis`, `cricket`, `esports`, `snooker`, `other`.'
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - final
          example: final
        description: Return only the carried terminal (finished) rows. `final` is the only accepted value — live rows are the default set, and `is_live=true` selects them alone. Case-insensitive. Any other value returns `400 validation_error` with `details.accepted` = `["final"]`.
      - name: is_live
        in: query
        required: false
        schema:
          type: string
          enum:
          - 'true'
          - 'false'
          example: 'true'
        description: '`true` returns live rows only, excluding every carried terminal row; `false` returns non-live rows only, which today means the carried terminal rows. Case-insensitive. Any other value — including `1` and `0` — returns `400 validation_error` with `details.accepted` = `["true","false"]`.'
      responses:
        '200':
          description: Live game state for the requested sport (envelope identical to `/gamestate`, just scoped to one sport)
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/DataEnvelope'
                - type: object
                  properties:
                    data:
                      type: object
                      description: Map with a single key (the path sport) whose value is a map of event_id → EventGameState.
                      additionalProperties:
                        type: object
                        additionalProperties:
                          $ref: '#/components/schemas/EventGameState'
              example:
                data:
                  soccer:
                    chile_-_primera_division_concepcion_palestino_2026-04-24:
                      home_team: Palestino
                      away_team: Concepción
                      sport: soccer
                      league: chile_-_primera_division
                      home_score: 0
                      away_score: 0
                      is_live: true
                      primary_book: unibet
                      book_count: 1
                      stale: true
                    montenegro_-_prva_liga_bokelj_otrantolympiculcinj_2026-04-23:
                      home_team: Bokelj
                      away_team: FK Otrant-Olympic Ulcinj
                      sport: soccer
                      league: montenegro_-_prva_liga
                      home_score: 2
                      away_score: 1
                      score_type: points
                      winner: home
                      status: final
                      completed_at: '2026-04-23T23:48:55Z'
                      is_live: false
                      stale: false
                updated_at: '2026-04-23T23:55:01.234Z'
        '400':
          description: Unrecognised `status` or `is_live` value. The error body names the accepted set in `details.accepted`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: validation_error
                  message: 'is_live must be one of: true, false'
                  details:
                    parameter: is_live
                    accepted:
                    - 'true'
                    - 'false'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/TierRestricted'
components:
  schemas:
    DataEnvelope:
      type: object
      description: Standard shape for non-paginated responses. Emitted by endpoints that return a single resource or a small fixed list. No `success` flag — HTTP status codes indicate success/failure.
      required:
      - data
      - updated_at
      properties:
        data: {}
        updated_at:
          type: string
          format: date-time
          description: Server emit time (RFC 3339).
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          properties:
            code:
              type: string
              enum:
              - missing_api_key
              - invalid_api_key
              - unauthorized
              - forbidden
              - tier_restricted
              - rate_limited
              - invalid_request
              - validation_error
              - not_found
              - streaming_not_available
              - stream_limit_exceeded
              - service_unavailable
              - internal_error
              description: Machine-readable error code
            message:
              type: string
              description: Human-readable error message
            docs:
              type: string
              format: uri
              description: Link to relevant documentation
            tier:
              type: string
              description: Current subscription tier
            required_tier:
              type: string
              description: Minimum tier required for this feature
            retry_after:
              type: integer
              description: Unix timestamp (ms) when request can be retried
            retryAfter:
              type: integer
              description: Seconds until the request can be retried — same instant as retry_after, different unit and casing
            max_books:
              type: integer
            requested_books:
              type: integer
    EventGameState:
      type: object
      description: 'Aggregated live game state for a single event, merged across the sportsbooks covering it. Scores are consensus-selected; temporal fields use sport-aware clock direction; situational fields priority-fill from a fixed book ranking. Every field is optional except the always-present core set — sport coverage varies, so e.g. tennis rows carry sets_home/server while hockey rows carry power_play. Rows also come in a terminal flavour: a fixture that has finished is carried here for 15 minutes after completion with status "final", completed_at, score_type and the final scores. A terminal row is projected from the completion record, not from a live cross-book merge, so it carries no primary_book/book_count/game_period/game_clock and no situational fields — branch on status == "final" before reading those.'
      required:
      - home_team
      - away_team
      - sport
      - league
      - is_live
      properties:
        home_team:
          type: string
          description: Normalized home team name.
        away_team:
          type: string
          description: Normalized away team name.
        sport:
          type: string
          description: Atlas sport id (e.g. `baseball`, `soccer`).
        league:
          type: string
          description: Atlas league id (e.g. `mlb`, `england_-_premier_league`).
        home_score:
          type: integer
          description: 'Current home score in the natural unit for the sport (runs, points, goals, sets — tennis uses summed set points). Present on live rows and on terminal rows whose `score_type` is `points`; a terminal row with `score_type: "sets"` carries `sets_home`/`sets_away` instead and omits this.'
        away_score:
          type: integer
          description: 'Current away score. Present on live rows and on terminal rows whose `score_type` is `points`; a terminal row with `score_type: "sets"` carries `sets_home`/`sets_away` instead and omits this.'
        is_live:
          type: boolean
          description: '`true` for a live event; `false` on a carried terminal (finished) row.'
        primary_book:
          type: string
          description: The sportsbook whose scores were selected by the merge. Consensus-respecting — if ≥2 books agree on a score the highest-priority book in that group wins. Live rows only — absent on a terminal row.
        book_count:
          type: integer
          description: Number of sportsbooks that contributed live state for this event at merge time. Live rows only — absent on a terminal row.
        game_period:
          type: string
          description: 'Current period. Sport-specific format: `T5` (MLB top 5), `Q3` (NBA Q3), `2H` (soccer 2nd half), `P2` (NHL P2), `S2` (tennis set 2), `FT` (full time).'
        game_clock:
          type: string
          description: Game clock. Countup format (`49:06`) for soccer; countdown format (`5:42`) for basketball/hockey/football.
        possession:
          type: string
          enum:
          - home
          - away
          description: Which team has possession (team sports) or is receiving (tennis).
        server:
          type: string
          enum:
          - home
          - away
          description: Tennis only — current server.
        last_play:
          type: string
          description: Sport-specific last-play description.
        is_timeout:
          type: boolean
          description: '`true` during a timeout.'
        fouls_home:
          type: integer
          description: Team fouls (basketball, soccer).
        fouls_away:
          type: integer
        corners_home:
          type: integer
          description: Soccer only.
        corners_away:
          type: integer
        yellow_cards_home:
          type: integer
          description: Soccer only.
        yellow_cards_away:
          type: integer
        red_cards_home:
          type: integer
          description: Soccer only.
        red_cards_away:
          type: integer
        power_play:
          type: string
          enum:
          - home
          - away
          description: Hockey only — which team is on the power play.
        sets_home:
          type: integer
          description: Tennis only — sets won.
        sets_away:
          type: integer
        hits_home:
          type: integer
          description: Baseball only.
        hits_away:
          type: integer
        home_pitcher:
          type: string
          description: Baseball only — starting pitcher display name.
        away_pitcher:
          type: string
        wickets_home:
          type: integer
          description: Cricket only — dismissals.
        wickets_away:
          type: integer
        overs:
          type: number
          description: Cricket only.
        batting_team:
          type: string
          enum:
          - home
          - away
          description: Cricket only.
        stale:
          type: boolean
          description: Only emitted when `true`. Indicates the `primary_book`'s livestate key TTL fell below the aggregator's freshness threshold (~10s) at merge time — scores reflect the last known values; the book has gone quiet. Absence of the field means fresh. On live rows it is written only when `true` (absence = fresh); a terminal row always carries it explicitly as `false`.
        aggregator_stale:
          type: boolean
          description: Only emitted when `true`. Indicates the SharpAPI aggregator itself hasn't advanced the gen counter for this event's sport in more than ~30s. Broader signal than `stale` — suggests a pipeline hiccup, not a single-book issue.
        status:
          type: string
          enum:
          - final
          description: Present only on a carried terminal row, always `final`. Live rows carry no `status` key, so `status == "final"` is the reliable terminal test.
        completed_at:
          type: string
          format: date-time
          description: Terminal rows only — when SharpAPI detected the completion (not a league-official final whistle). The 15-minute carry window is measured from this timestamp.
        score_type:
          type: string
          enum:
          - points
          - sets
          description: Terminal rows only — which fields carry the final result. `sets` for the set-scored sports (`tennis`, `table_tennis`, `volleyball`, `badminton`), whose result is in `sets_home`/`sets_away`; `points` everywhere else, whose result is in `home_score`/`away_score`.
        winner:
          type: string
          enum:
          - home
          - away
          - draw
          description: 'Terminal rows only, and optional even there — omitted when the recorded result does not settle the match (a level score in a sport that cannot draw, a sub-terminal set count, or a snapshot whose scores never arrived and is recorded as 0-0). A missing `winner` means "not settled", not a tie. `draw` is produced only for sports where a level score is a real outcome: `soccer`, `hockey`, `football`, `rugby_union`, `rugby_league`.'
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missing:
              summary: Missing API key
              value:
                error:
                  code: missing_api_key
                  message: API key required
                  docs: https://docs.sharpapi.io/en/authentication#authentication-methods
            invalid:
              summary: Invalid API key
              value:
                error:
                  code: invalid_api_key
                  message: Invalid API key
                  docs: https://docs.sharpapi.io/en/authentication#authentication-methods
    TierRestricted:
      description: Feature requires a higher subscription tier
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: tier_restricted
              message: EV opportunities requires pro tier or higher
              tier: hobby
              required_tier: pro
              docs: https://sharpapi.io/pricing
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key passed in the `X-API-Key` header
    BearerAuth:
      type: http
      scheme: bearer
      description: API key passed as a Bearer token in the `Authorization` header
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: API key as query parameter (for SSE/EventSource only)