{
  "openapi": "3.1.0",
  "info": {
    "version": "2.0.0",
    "title": "SockOdds API",
    "description": "The Australian extension of the SportsGameOdds v2 schema: every Australian bookmaker, AFL, NRL, cricket and rugby alongside the world's leagues. Same paths, envelope and oddID grammar as api.sportsgameodds.com/v2.",
    "contact": {
      "name": "SockOdds Support",
      "email": "api@sockodds.com"
    },
    "termsOfService": "https://sockodds.com/terms/"
  },
  "servers": [
    {
      "url": "https://api.sockodds.com/v2",
      "description": "SockOdds production"
    }
  ],
  "security": [
    {
      "ApiKeyHeader": []
    },
    {
      "ApiKeyParam": []
    }
  ],
  "paths": {
    "/events/": {
      "get": {
        "operationId": "getEvents",
        "tags": [
          "Events"
        ],
        "summary": "Get a list of Events",
        "description": "Retrieve sports events with odds, status, teams, players, results and bookmaker links. Filter by league, team, date or odds market. Includes every bookmaker line your plan allows.\n\nWhen you provide eventID or eventIDs, the API uses only those IDs to fetch results — all other query filters (sportID, leagueID, live, started, finalized, startsAfter, startsBefore, includeFinished) are ignored. Response-shaping parameters like oddID, bookmakerID, playerID, includeAltLines and includeOpposingOdds still apply.",
        "parameters": [
          {
            "name": "eventID",
            "in": "query",
            "required": false,
            "description": "An eventID to get Event data for",
            "schema": {
              "type": "string"
            },
            "example": "afl_2026-09-12_brisbane_lions_vs_adelaide_crows"
          },
          {
            "name": "eventIDs",
            "in": "query",
            "required": false,
            "description": "A comma separated list of eventIDs to get Event data for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sportID",
            "in": "query",
            "required": false,
            "description": "A sportID or comma-separated list of sportIDs to get Events for",
            "schema": {
              "type": "string"
            },
            "example": "AUSSIE_RULES"
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "A leagueID or comma-separated list of leagueIDs to get Events for",
            "schema": {
              "type": "string"
            },
            "example": "AFL,NRL"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Only include Events of the specified type (match, tournament, prop)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "oddsAvailable",
            "in": "query",
            "required": false,
            "description": "Whether you want only Events which do (true) or do not (false) have odds markets which are currently available (open for wagering)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "oddsPresent",
            "in": "query",
            "required": false,
            "description": "Whether you want only Events which do (true) or do not (false) have any associated odds markets regardless of whether those odds markets are currently available",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "oddID",
            "in": "query",
            "required": false,
            "description": "An oddID or comma-separated list of oddIDs to include odds for. Replace the playerID slot with PLAYER_ID to match every player. `oddIDs` is accepted as an alias.",
            "schema": {
              "type": "string"
            },
            "example": "points-home-game-ml-home"
          },
          {
            "name": "includeOpposingOdds",
            "in": "query",
            "required": false,
            "description": "Whether to include opposing odds for each included oddID (`includeOpposingOddIDs` is accepted as an alias)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeAltLines",
            "in": "query",
            "required": false,
            "description": "Whether to include alternate lines in the odds byBookmaker data. Off by default — alt lines can multiply the payload.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "expandResults",
            "in": "query",
            "required": false,
            "description": "Whether to expand the results object to include all stat values rather than just the base set (Accepted for compatibility. SockOdds always returns every result value the source carries, so this flag has no effect.)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeOpenCloseOdds",
            "in": "query",
            "required": false,
            "description": "Whether to include open and close odds values (openOdds, closeOdds, openSpread, closeSpread, openOverUnder, closeOverUnder) in the odds byBookmaker data (Accepted for compatibility. SockOdds does not snapshot opening and closing prices yet, so these fields are absent whatever you pass.)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "bookmakerID",
            "in": "query",
            "required": false,
            "description": "A bookmakerID or comma-separated list of bookmakerIDs to include odds for",
            "schema": {
              "type": "string"
            },
            "example": "sportsbet,tab"
          },
          {
            "name": "teamID",
            "in": "query",
            "required": false,
            "description": "A teamID or comma-separated list of teamIDs to include Events for",
            "schema": {
              "type": "string"
            },
            "example": "BRISBANE_LIONS_AFL"
          },
          {
            "name": "playerID",
            "in": "query",
            "required": false,
            "description": "A playerID or comma-separated list of playerIDs to include Events (and associated odds) for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finalized",
            "in": "query",
            "required": false,
            "description": "Only include finalized Events (true), exclude unfinalized Events (false) or all Events (omit)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "live",
            "in": "query",
            "required": false,
            "description": "Only include live Events (true), only non-live Events (false) or all Events (omit)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "started",
            "in": "query",
            "required": false,
            "description": "Only include Events which have previously started (true), only Events which have not previously started (false) or all Events (omit)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "ended",
            "in": "query",
            "required": false,
            "description": "Only include Events which have ended (true), only Events which have not ended (false) or all Events (omit)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "cancelled",
            "in": "query",
            "required": false,
            "description": "Only include cancelled Events (true), only non-cancelled Events (false) or all Events (omit)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "startsAfter",
            "in": "query",
            "required": false,
            "description": "Get Events that start after this date",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-09-01T00:00:00Z"
          },
          {
            "name": "startsBefore",
            "in": "query",
            "required": false,
            "description": "Get Events that start before this date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "includeFinished",
            "in": "query",
            "required": false,
            "description": "SockOdds extension. Without a date window, eventID or this flag, events that kicked off more than 24 hours ago are omitted. Pass true to list everything the store retains. (SockOdds-only parameter; SportsGameOdds ignores it.)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "The maximum number of Events to return (default 10, max 100)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor for the request. Used to get the next group of results. This is an opaque token — pass the nextCursor value from the prior response unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          },
          "500": {
            "description": "Query failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Query failed"
                }
              }
            }
          }
        }
      }
    },
    "/odds/history/": {
      "get": {
        "operationId": "getOddsHistory",
        "tags": [
          "Odds"
        ],
        "summary": "Get the tick-by-tick odds history of an Event",
        "description": "SockOdds extension. Every price, line and bet-limit change every bookmaker has published for one event, oldest first — the raw movement behind opening, closing and steam. Captured since 2026-08-14 and kept indefinitely; the last ~28 days are answered from the live store and everything older from the archive.\n\nFilter with oddID and bookmakerID — an NFL game logs ~25,000 ticks a day, and each request reads at most 50,000 ticks per tier before paging. Your plan's league scope and bookmaker cap apply exactly as on /events/. One bookmaker is one series: where a book reaches the log under two sources, the higher-ranked source is kept for the whole window. `notice` says when the archive tier did not answer, in which case the series is incomplete at its old end.",
        "parameters": [
          {
            "name": "eventID",
            "in": "query",
            "required": false,
            "description": "The eventID to get odds history for (required)",
            "schema": {
              "type": "string"
            },
            "example": "afl_2026-09-12_brisbane_lions_vs_adelaide_crows"
          },
          {
            "name": "oddID",
            "in": "query",
            "required": false,
            "description": "An oddID or comma-separated list of oddIDs to include ticks for. `oddIDs` is accepted as an alias.",
            "schema": {
              "type": "string"
            },
            "example": "points-home-game-ml-home"
          },
          {
            "name": "bookmakerID",
            "in": "query",
            "required": false,
            "description": "A bookmakerID or comma-separated list of bookmakerIDs to include ticks for",
            "schema": {
              "type": "string"
            },
            "example": "sportsbet,pinnacle"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start of the window. Defaults to 21 days before the event's kickoff date.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-08-22T00:00:00Z"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End of the window (exclusive, capped at now). Defaults to 2 days after kickoff. from/to may span at most 400 days.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "The maximum number of ticks to return (default 1000, max 5000)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor for the request. Used to get the next group of results. This is an opaque token — pass the nextCursor value from the prior response unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OddsHistoryTick"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Not found"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          },
          "500": {
            "description": "Query failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Query failed"
                }
              }
            }
          },
          "503": {
            "description": "503",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false
                }
              }
            }
          }
        }
      }
    },
    "/teams/": {
      "get": {
        "operationId": "getTeams",
        "tags": [
          "Teams"
        ],
        "summary": "Get a list of Teams by ID or league",
        "description": "Retrieve team information including names, colours and identifiers. Filter by teamID, leagueID or sportID. Supports pagination.",
        "parameters": [
          {
            "name": "sportID",
            "in": "query",
            "required": false,
            "description": "A single sportID or comma-separated list of sportIDs to get Teams for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "A single leagueID or comma-separated list of leagueIDs to get Teams for",
            "schema": {
              "type": "string"
            },
            "example": "AFL"
          },
          {
            "name": "teamID",
            "in": "query",
            "required": false,
            "description": "A single teamID or comma-separated list of teamIDs to get data for",
            "schema": {
              "type": "string"
            },
            "example": "BRISBANE_LIONS_AFL"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "The maximum number of Teams to return (default 50, max 250)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor for the request. Used to get the next group of results. This is an opaque token — pass the nextCursor value from the prior response unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Team"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          },
          "500": {
            "description": "Query failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Query failed"
                }
              }
            }
          }
        }
      }
    },
    "/players/": {
      "get": {
        "operationId": "getPlayers",
        "tags": [
          "Players"
        ],
        "summary": "Get a list of Players for a specific Team or Event",
        "description": "Retrieve player information including names, team and identifiers. Filter by playerID, teamID or eventID. Supports pagination.",
        "parameters": [
          {
            "name": "teamID",
            "in": "query",
            "required": false,
            "description": "TeamID to get Players data for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventID",
            "in": "query",
            "required": false,
            "description": "EventID to get Players data for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "playerID",
            "in": "query",
            "required": false,
            "description": "PlayerID to get data for",
            "schema": {
              "type": "string"
            },
            "example": "SONNY_GRAY_1_MLB"
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "SockOdds extension: a leagueID or comma-separated list to scope the player list (SockOdds-only parameter.)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "The maximum number of Players to return (default 50, max 250)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor for the request. Used to get the next group of results. This is an opaque token — pass the nextCursor value from the prior response unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Player"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          },
          "500": {
            "description": "Query failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Query failed"
                }
              }
            }
          }
        }
      }
    },
    "/sports/": {
      "get": {
        "operationId": "getSports",
        "tags": [
          "Sports"
        ],
        "summary": "Get a list of sports",
        "description": "Retrieve all supported sports with their sportID values.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Sport"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      }
    },
    "/leagues/": {
      "get": {
        "operationId": "getLeagues",
        "tags": [
          "Leagues"
        ],
        "summary": "Get a list of Leagues",
        "description": "Retrieve all supported leagues with leagueID values. `enabled` reflects what your plan can see.",
        "parameters": [
          {
            "name": "sportID",
            "in": "query",
            "required": false,
            "description": "The sport to get leagues for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "The league to get data for",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/League"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      }
    },
    "/stats/": {
      "get": {
        "operationId": "getStats",
        "tags": [
          "Stats"
        ],
        "summary": "Get a list of StatIDs",
        "description": "Retrieve all supported statistics with statID values. Filter by sportID and by the level (all, team, player) the stat is priced at.",
        "parameters": [
          {
            "name": "statID",
            "in": "query",
            "required": false,
            "description": "StatID to get data for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sportID",
            "in": "query",
            "required": false,
            "description": "SportID to get StatIDs for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statLevel",
            "in": "query",
            "required": false,
            "description": "Level of the stat, must be used in combination with sportID. Must be one of all, player, or team. Shows stats that are applicable to that specified entity, defaults to all.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Stat"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      }
    },
    "/markets/": {
      "get": {
        "operationId": "getMarkets",
        "tags": [
          "Markets"
        ],
        "summary": "Get a list of Markets",
        "description": "Retrieve metadata about markets, keyed by oddID: identifiers, display names, classification (main markets, props, prop type, sub-periods) and which leagues and bookmakers currently price each one.",
        "parameters": [
          {
            "name": "oddID",
            "in": "query",
            "required": false,
            "description": "A single oddID or comma-separated list of oddIDs. Used to specify specific Markets to return.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sportID",
            "in": "query",
            "required": false,
            "description": "A single sportID or comma-separated list of sportIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "A single leagueID or comma-separated list of leagueIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bookmakerID",
            "in": "query",
            "required": false,
            "description": "A single bookmakerID or comma-separated list of bookmakerIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statID",
            "in": "query",
            "required": false,
            "description": "A single statID or comma-separated list of statIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "statEntityID",
            "in": "query",
            "required": false,
            "description": "A single statEntityID or comma-separated list of statEntityIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodID",
            "in": "query",
            "required": false,
            "description": "A single periodID or comma-separated list of periodIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "betTypeID",
            "in": "query",
            "required": false,
            "description": "A single betTypeID or comma-separated list of betTypeIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sideID",
            "in": "query",
            "required": false,
            "description": "A single sideID or comma-separated list of sideIDs to filter Markets by",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "isMainMarket",
            "in": "query",
            "required": false,
            "description": "Filter to only include main markets (main period moneyline, spread, and over/under)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "isProp",
            "in": "query",
            "required": false,
            "description": "Filter by whether it is any type of prop bet market",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "isSubPeriod",
            "in": "query",
            "required": false,
            "description": "Filter by whether it tracks a sub/non-main period",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "propType",
            "in": "query",
            "required": false,
            "description": "Filter by prop type (game_prop, team_prop, player_prop, other_prop)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "isSupported",
            "in": "query",
            "required": false,
            "description": "Filter whether this market is priced by at least 1 bookmaker in at least 1 league. Defaults to true if not specified.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "The maximum number of Markets to return (default: 100, max: 10000)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor for the request. Used to get the next group of results. This is an opaque token — pass the nextCursor value from the prior response unchanged.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Market"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid params",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid params"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          },
          "500": {
            "description": "Query failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Query failed"
                }
              }
            }
          }
        }
      }
    },
    "/account/usage": {
      "get": {
        "operationId": "getUsageData",
        "tags": [
          "Account"
        ],
        "summary": "Get rate-limits and usage data about your API key",
        "description": "Check your API key's tier, rate limits and current usage by interval. Calling it counts as a request like any other.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AccountUsage"
                      }
                    },
                    "nextCursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "notice": {
                      "$ref": "#/components/schemas/Notice"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Invalid API key"
                }
              }
            }
          },
          "403": {
            "description": "Inactive API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Inactive API key"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Not found"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      }
    },
    "/stream/events": {
      "get": {
        "operationId": "streamEvents",
        "tags": [
          "Stream"
        ],
        "summary": "Setup streamed (WebSocket) connection",
        "description": "Reserved. SockOdds does not stream: the source refreshes every ~2 minutes and this endpoint answers 501 so a client written for SportsGameOdds fails loudly instead of waiting on a socket that never opens.",
        "parameters": [
          {
            "name": "feed",
            "in": "query",
            "required": false,
            "description": "The feed you would like to subscribe to (events:live, events:upcoming, events:byid)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "leagueID",
            "in": "query",
            "required": false,
            "description": "A leagueID to stream events for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventID",
            "in": "query",
            "required": false,
            "description": "An eventID to stream events for",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "error": "Not implemented"
                }
              }
            }
          }
        }
      }
    },
    "/account/keys/rotate": {
      "post": {
        "operationId": "rotateApiKey",
        "tags": [
          "Account"
        ],
        "summary": "Rotate the calling API key",
        "description": "Creates a replacement with the same customer and tier, then atomically disables the calling key. The new raw key is returned once.",
        "responses": {
          "201": {
            "description": "Replacement key created"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Inactive API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/account/keys/current": {
      "delete": {
        "operationId": "revokeApiKey",
        "tags": [
          "Account"
        ],
        "summary": "Revoke the calling API key",
        "description": "Immediately disables the calling key. This cannot be undone.",
        "responses": {
          "204": {
            "description": "Key revoked"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Inactive API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      },
      "ApiKeyParam": {
        "type": "apiKey",
        "in": "query",
        "name": "apiKey"
      }
    },
    "schemas": {
      "OddsHistoryTick": {
        "type": "object",
        "description": "One recorded change to one bookmaker's price on one market (SockOdds extension). Odds are given as American strings (bookOdds) and decimals.",
        "properties": {
          "eventID": {
            "type": "string",
            "description": "The event"
          },
          "oddID": {
            "type": "string",
            "description": "The market side, in the oddID format (statID-statEntityID-periodID-betTypeID-sideID)"
          },
          "bookmakerID": {
            "type": "string",
            "description": "The bookmaker"
          },
          "changedAt": {
            "type": "string",
            "description": "When the bookmaker's quote changed"
          },
          "kind": {
            "type": "string",
            "description": "open = first quote seen · move = price, line or main-line status changed · limit = only the bet limit changed (Pinnacle) · close = the quote was withdrawn"
          },
          "bookOdds": {
            "type": "string",
            "nullable": true,
            "description": "The new price as American odds; null on a close"
          },
          "decimalOdds": {
            "type": "number",
            "nullable": true,
            "description": "The new price as decimal odds"
          },
          "previousBookOdds": {
            "type": "string",
            "nullable": true,
            "description": "The price this change replaced (American); null on an open"
          },
          "previousDecimalOdds": {
            "type": "number",
            "nullable": true,
            "description": "The price this change replaced (decimal)"
          },
          "line": {
            "type": "number",
            "nullable": true,
            "description": "The spread or total the price applies to; null for moneylines and yes/no markets"
          },
          "isMainLine": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether this line was the bookmaker's headline line at the time"
          },
          "layOdds": {
            "type": "number",
            "nullable": true,
            "description": "Exchange lay price, where the bookmaker is an exchange"
          },
          "maxStake": {
            "type": "number",
            "nullable": true,
            "description": "The bet limit after the change, where the bookmaker publishes one"
          },
          "previousMaxStake": {
            "type": "number",
            "nullable": true,
            "description": "The bet limit before the change"
          }
        }
      },
      "Event": {
        "type": "object",
        "description": "Contains basic information, consensus odds, results (stats & scores), team info, lineups and bookmaker links for a given event/game",
        "properties": {
          "eventID": {
            "type": "string",
            "description": "Unique identifier for the event (e.g. afl_2026-09-12_brisbane_lions_vs_adelaide_crows)"
          },
          "sportID": {
            "type": "string",
            "description": "The sport (AUSSIE_RULES, RUGBY_LEAGUE, SOCCER, …)"
          },
          "leagueID": {
            "type": "string",
            "description": "The league (AFL, NRL, RUGBYLEAGUE_NRLW, EPL, …) — always the feed's own key, never constructed"
          },
          "type": {
            "type": "string",
            "description": "match, tournament or prop"
          },
          "status": {
            "type": "object",
            "description": "started, ended, live, cancelled, delayed, finalized, completed, startsAt, oddsPresent, oddsAvailable, currentPeriodID, periods{started,ended}, displayShort/displayLong"
          },
          "info": {
            "type": "object",
            "description": "displayName, commenceTime, lastUpdatedAt, stale (no source write for 45 min), bookmakersPresent, sourceBookmakerCount"
          },
          "teams": {
            "type": "object",
            "description": "home/away → { teamID, names{long,medium,short}, colors, statEntityID, score }"
          },
          "players": {
            "type": "object",
            "description": "playerID → { playerID, teamID, name, firstName, lastName } — the production SGO player ids"
          },
          "results": {
            "type": "object",
            "description": "Nested results in the format {periodID}.{statEntityID}.{statID} → number, where the source carries them"
          },
          "odds": {
            "type": "object",
            "description": "oddID → Odds object. Every market the event is priced on, all bookmakers nested under byBookmaker"
          },
          "links": {
            "type": "object",
            "description": "bookmakers{bookmakerID → event URL} and betslip{bookmakerID → bet-slip strategy} deeplinks, straight from each book's own event ids"
          }
        }
      },
      "Odds": {
        "type": "object",
        "description": "One side of one market on one event, with every bookmaker's price nested inside",
        "properties": {
          "oddID": {
            "type": "string",
            "description": "{statID}-{statEntityID}-{periodID}-{betTypeID}-{sideID}"
          },
          "opposingOddID": {
            "type": "string",
            "nullable": true,
            "description": "The oddID of the other side (over ↔ under, home ↔ away); null for pick-N markets"
          },
          "marketName": {
            "type": "string",
            "description": "Human-readable market name, e.g. \"Head to Head — Brisbane Lions\""
          },
          "statID": {
            "type": "string",
            "description": "The statistic being wagered on"
          },
          "statEntityID": {
            "type": "string",
            "description": "home, away, all, a playerID or a teamID"
          },
          "periodID": {
            "type": "string",
            "description": "game, 1h, 1q, 1i, 1ix5, 1s, …"
          },
          "betTypeID": {
            "type": "string",
            "description": "ml, sp, ou, ml3way, yn, eo, pick, …"
          },
          "sideID": {
            "type": "string",
            "description": "home, away, over, under, yes, no, draw, …"
          },
          "playerID": {
            "type": "string",
            "description": "Set when the market is a player prop"
          },
          "bookOdds": {
            "type": "string",
            "description": "Consensus American price across the books pricing this side, e.g. \"-108\" (the vig left in)"
          },
          "bookOddsAvailable": {
            "type": "boolean",
            "description": "Whether at least one bookmaker has this side open for wagering"
          },
          "bookSpread": {
            "type": "string",
            "nullable": true,
            "description": "Consensus line for spread and total markets"
          },
          "fairOdds": {
            "type": "string",
            "nullable": true,
            "description": "The de-vigged fair price derived from exchange and sharp-book consensus; null on plans without fair odds"
          },
          "fairOddsAvailable": {
            "type": "boolean",
            "description": "Whether enough exchange/sharp data existed to compute fairOdds"
          },
          "fairSpread": {
            "type": "string",
            "nullable": true,
            "description": "The fair line for spread and total markets"
          },
          "started": {
            "type": "boolean",
            "description": "Whether the period this market settles on has started, ended or been cancelled"
          },
          "scoringSupported": {
            "type": "boolean",
            "description": "Whether the source can grade this market from results"
          },
          "byBookmaker": {
            "type": "object",
            "description": "bookmakerID → ByBookmakerOdds"
          },
          "altLines": {
            "type": "object",
            "description": "Alternate lines keyed by line, each with its own byBookmaker (only with includeAltLines=true)"
          }
        }
      },
      "ByBookmakerOdds": {
        "type": "object",
        "description": "One bookmaker's price for one side of one market",
        "properties": {
          "bookmakerID": {
            "type": "string",
            "description": "The bookmaker (sportsbet, tab, pinnacle, betfairexchange, …)"
          },
          "odds": {
            "type": "string",
            "description": "American price, e.g. \"-108\" or \"+240\""
          },
          "decimal": {
            "type": "number",
            "description": "The same price as decimal odds, e.g. 1.93 — Australian books quote decimal"
          },
          "overUnder": {
            "type": "string",
            "description": "This book's line where the market has one"
          },
          "available": {
            "type": "boolean",
            "description": "Whether the book has the side open right now (a suspended market is listed with available: false)"
          },
          "lastUpdatedAt": {
            "type": "string",
            "description": "When this book's price was last observed"
          },
          "eventName": {
            "type": "string",
            "description": "The book's own name for the event"
          },
          "deeplink": {
            "type": "string",
            "description": "Direct URL to the market on the book where one is known (also see Event.links)"
          }
        }
      },
      "Team": {
        "type": "object",
        "description": "Contains information on a team",
        "properties": {
          "teamID": {
            "type": "string",
            "description": "e.g. BRISBANE_LIONS_AFL — defined per league"
          },
          "sportID": {
            "type": "string",
            "description": ""
          },
          "leagueID": {
            "type": "string",
            "description": ""
          },
          "names": {
            "type": "object",
            "description": "{ long, medium, short }"
          },
          "colors": {
            "type": "object",
            "description": "{ primary, secondary, primaryContrast, secondaryContrast } where known"
          },
          "statEntityID": {
            "type": "string",
            "description": "home or away on the event the team was read from"
          }
        }
      },
      "Player": {
        "type": "object",
        "description": "Contains information on a player",
        "properties": {
          "playerID": {
            "type": "string",
            "description": "e.g. SONNY_GRAY_1_MLB — the production SportsGameOdds id format, unique across teams in a league"
          },
          "teamID": {
            "type": "string",
            "description": ""
          },
          "sportID": {
            "type": "string",
            "description": ""
          },
          "leagueID": {
            "type": "string",
            "description": ""
          },
          "name": {
            "type": "string",
            "description": ""
          },
          "position": {
            "type": "number",
            "description": "Where the source carries them"
          }
        }
      },
      "Sport": {
        "type": "object",
        "description": "Contains information on a sport",
        "properties": {
          "sportID": {
            "type": "string",
            "description": ""
          },
          "name": {
            "type": "string",
            "description": ""
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether your plan can read this sport"
          },
          "activeEvents": {
            "type": "number",
            "description": "Events currently carried"
          }
        }
      },
      "League": {
        "type": "object",
        "description": "Contains information on a specific league",
        "properties": {
          "leagueID": {
            "type": "string",
            "description": ""
          },
          "sportID": {
            "type": "string",
            "description": ""
          },
          "name": {
            "type": "string",
            "description": ""
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether your plan can read this league"
          },
          "activeEvents": {
            "type": "number",
            "description": "Events currently carried"
          }
        }
      },
      "Stat": {
        "type": "object",
        "description": "Contains information on a statistic (statID)",
        "properties": {
          "statID": {
            "type": "string",
            "description": ""
          },
          "supportedLevels": {
            "type": "object",
            "description": "{ all, team, player } — which statEntityID classes it is priced at"
          },
          "displays": {
            "type": "object",
            "description": "{ short, long }"
          },
          "isScoreStat": {
            "type": "boolean",
            "description": "True for `points`, the stat that decides the event"
          },
          "supportedSports": {
            "type": "object",
            "description": "sportID → true"
          }
        }
      },
      "Market": {
        "type": "object",
        "description": "Contains information about a betting market, including its classification and support data across leagues and bookmakers",
        "properties": {
          "oddID": {
            "type": "string",
            "description": "The unique identifier for this market"
          },
          "statID": {
            "type": "string",
            "description": "The decomposed grammar"
          },
          "playerID": {
            "type": "string",
            "description": "Set for player props and tournament team markets"
          },
          "marketGroupID": {
            "type": "string",
            "description": "The group (all sides of the market) this market belongs to, and its display name"
          },
          "isMainMarket": {
            "type": "boolean",
            "description": "True for the full-game moneyline, spread and total"
          },
          "isMainDerivative": {
            "type": "boolean",
            "description": "True for a sub-period of a main market"
          },
          "isSubPeriod": {
            "type": "boolean",
            "description": "True when the market tracks a non-main period"
          },
          "isProp": {
            "type": "boolean",
            "description": "True if this is a prop bet"
          },
          "propType": {
            "type": "string",
            "description": "game_prop, team_prop, player_prop or other_prop"
          },
          "isSupported": {
            "type": "boolean",
            "description": "True if at least one bookmaker prices it in at least one league"
          },
          "activeEvents": {
            "type": "number",
            "description": "Unique events with this market priced right now"
          },
          "support": {
            "type": "object",
            "description": "leagueID → { bookmakerID → true }"
          },
          "bookmakers": {
            "type": "array",
            "description": "SockOdds extension: the flat list of bookmakers pricing it"
          }
        }
      },
      "AccountUsage": {
        "type": "object",
        "description": "Your API key's tier, rate limits and current usage",
        "properties": {
          "keyID": {
            "type": "string",
            "description": "The hashed identifier for the API key (the first 16 hex of sha256)"
          },
          "customerID": {
            "type": "string",
            "nullable": true,
            "description": "Billing customer id where one exists"
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": ""
          },
          "isActive": {
            "type": "boolean",
            "description": ""
          },
          "tier": {
            "type": "string",
            "description": "lite, base or internal"
          },
          "rateLimits": {
            "type": "object",
            "description": "per-second / per-minute / per-hour / per-day / per-month → RateLimitInterval"
          }
        }
      },
      "RateLimitInterval": {
        "type": "object",
        "description": "One rate-limit window",
        "properties": {
          "max-requests": {
            "type": "number",
            "nullable": true,
            "description": "Maximum allowed requests in the interval (null = unlimited)"
          },
          "current-requests": {
            "type": "number",
            "description": "Requests made so far in the interval"
          },
          "max-entities": {
            "type": "number",
            "nullable": true,
            "description": "Maximum objects in the interval (null = unlimited)"
          },
          "current-entities": {
            "type": "number",
            "nullable": true,
            "description": "Objects served so far in the interval"
          }
        }
      },
      "StreamEventsPusherResponse": {
        "type": "object",
        "description": "Reserved. SockOdds answers 501 on /stream/events."
      },
      "NextCursor": {
        "type": "string",
        "nullable": true,
        "description": "Opaque cursor for the next page; null when there is no more."
      },
      "Notice": {
        "type": "string",
        "description": "Present when the key's plan removed events or bookmaker odds from the response."
      },
      "DateTime": {
        "type": "string",
        "format": "date-time"
      }
    }
  }
}