List markets
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Get, RequestUri = new Uri("https://oddslink.app/v1/markets?sport=soccer"), Headers = { { "X-API-Key", "<X-API-Key>" }, },};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://oddslink.app/v1/markets?sport=soccer"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<X-API-Key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url("https://oddslink.app/v1/markets?sport=soccer") .get() .addHeader("X-API-Key", "<X-API-Key>") .build();
Response response = client.newCall(request).execute();const url = 'https://oddslink.app/v1/markets?sport=soccer';const options = {method: 'GET', headers: {'X-API-Key': '<X-API-Key>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://oddslink.app/v1/markets?sport=soccer' \ --header 'X-API-Key: <X-API-Key>'Every market we serve, one entry per market key and period, with the sports it applies to and a short description. An entry with no period is the full-game market; baseball’s only period is f5 (first 5 innings) and there are no F3 or F7 markets. Pass key to markets and period to periods. kind says which endpoint takes the key: game_line keys go to /v1/sports/{sport}/odds, player_prop keys to /v1/sports/{sport}/props, where markets is required. Without sport, bookmakers is every book that carries the market in any of its sports. Pass sport to list only that sport’s markets, each with only the books that carry it for that sport and sports set to that one sport tag.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters”Optional sport key, for example nfl, soccer, epl or tennis. A soccer league key answers as soccer and a tennis tournament key as tennis: markets and books are listed per sport, not per competition; any well-formed tennis tournament key answers as tennis. A key that is not a sport key returns 404.
Example
soccerResponses
Section titled “ Responses ”Every market key we carry, or those of one sport.
object
The market key exactly as it appears in markets[].key (or a prop row’s stat), and the value markets takes.
The slice of the game a market settles on: 1h/2h halves, 1q..4q quarters, 1p..3p hockey periods, f5 baseball’s first 5 innings, 1i baseball’s first inning, 1s..5s tennis sets, reg hockey regulation time. Absent on a full-game market; never full. More periods may be added. There are no F3 or F7 markets. Esports map periods are map1 through map5; full-match markets omit the period field.
Whether this market’s outcomes carry a point (a spread, a total line, or a player prop’s line). False for a fixed choice among outcomes (moneyline, both-teams-to-score, draw-no-bet, double chance) and for a player prop that is simply true or false (anytime touchdown scorer, double-double).
game_line or player_prop. Treat the list as open: a new kind may be added. game_line is a market on the fixture, served by /v1/sports/{sport}/odds. player_prop is a market on one named player, served by /v1/sports/{sport}/props, where markets is required.
Sport tags this market applies to. Coarse (nfl, soccer, tennis), not the per-league /v1/sports keys.
Book keys known to carry this market: measured game-line coverage or source-backed player-prop mappings within supported sports. With ?sport=, only the books that carry it for that sport. Describes capability, not current availability on a fixture. Omitted where coverage is unverified, including period props without an explicit mapping. Never assumes every props book carries every prop market.
Examples
A full-game market, a first-5-innings one, and a player prop
[ { "key": "h2h", "description": "Two-way match winner; soccer includes the draw.", "has_point": false, "kind": "game_line", "sports": [ "mlb", "mma", "nba", "ncaaf", "nfl", "nhl", "soccer", "tennis", "wnba" ], "bookmakers": [ "1xbet", "4casters", "888sport", "ballybet", "bet105", "bet365", "betano", "betfair", "betmgm", "betonline", "betr", "betrivers", "betus", "betway", "bovada", "bwin", "caesars", "circa", "cloudbet", "draftkings", "fanatics", "fanaticsmarkets", "fanduel", "fliff", "hardrock", "kalshi", "ladbrokes", "lowvig", "matchbook", "novig", "pinnacle", "polymarket", "prophetx", "rebet", "sbobet", "shuffle", "skybet", "sportbet", "stake", "sxbet", "thescore", "thunderpick", "unibet", "williamhill" ] }, { "key": "totals", "period": "f5", "description": "Combined score, over or under a line (total games in tennis).", "has_point": true, "kind": "game_line", "sports": [ "mlb" ], "bookmakers": [ "ballybet", "bet105", "bet365", "betmgm", "betonline", "betr", "betrivers", "betus", "betway", "bovada", "bwin", "cloudbet", "draftkings", "fanatics", "fanaticsmarkets", "fanduel", "fliff", "hardrock", "kalshi", "lowvig", "novig", "pinnacle", "polymarket", "prophetx", "rebet", "sbobet", "shuffle", "sportbet", "stake", "thescore", "thunderpick", "unibet" ] }, { "key": "player_pass_yds", "description": "Passing yards.", "has_point": true, "kind": "player_prop", "sports": [ "ncaaf", "nfl" ], "bookmakers": [ "1xbet", "4casters", "888sport", "ballybet", "bet365", "betano", "betfair", "betmgm", "betonline", "betr", "betrivers", "betway", "bovada", "bwin", "caesars", "circa", "cloudbet", "draftkings", "fanatics", "fanaticsmarkets", "fanduel", "fliff", "hardrock", "kalshi", "lowvig", "matchbook", "novig", "pinnacle", "polymarket", "prizepicks", "prophetx", "rebet", "shuffle", "skybet", "sxbet", "thescore", "thunderpick", "underdog", "unibet" ] }]Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.
A parameter was malformed.
object
object
Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.
Valid case-sensitive book keys on INVALID_BOOKMAKER.
403 only: the plan on the presented key.
403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.
Example
{ "error": { "code": "BAD_REQUEST", "message": "commenceTimeFrom is not a valid ISO-8601 timestamp.", "docs_url": "https://oddslink.app/docs/errors/#bad-request", "request_id": "req_01hz8k3z9e2v6w1x" }}Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.
The X-API-Key header is missing or invalid.
object
object
Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.
Valid case-sensitive book keys on INVALID_BOOKMAKER.
403 only: the plan on the presented key.
403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.
Examples
No X-API-Key header sent
{ "error": { "code": "MISSING_KEY", "message": "X-API-Key header is missing.", "docs_url": "https://oddslink.app/docs/errors/#missing-key", "request_id": "req_01hz8k4a1f3w7x2y" }}Key does not exist or was revoked
{ "error": { "code": "INVALID_KEY", "message": "API key is not valid.", "docs_url": "https://oddslink.app/docs/errors/#invalid-key", "request_id": "req_01hz8k4b2g4x8y3z" }}Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.
The sport key does not exist.
object
object
Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.
Valid case-sensitive book keys on INVALID_BOOKMAKER.
403 only: the plan on the presented key.
403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.
Example
{ "error": { "code": "UNKNOWN_SPORT", "message": "Unknown sport key: basketbal_nba", "docs_url": "https://oddslink.app/docs/errors/#unknown-sport", "request_id": "req_01hz8k4d4j6z0a5b" }}Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.
The plan’s speed limit was exceeded; wait Retry-After seconds. A call that does not count against the allowance is never refused for a spent allowance.
object
object
Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.
Valid case-sensitive book keys on INVALID_BOOKMAKER.
403 only: the plan on the presented key.
403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.
Example
{ "error": { "code": "SPEED_LIMIT", "message": "Speed limit exceeded: 10 requests/second on the Growth plan.", "docs_url": "https://oddslink.app/docs/errors/#speed-limit", "request_id": "req_01hz8k4f7m9c3d8f" }}Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.
Seconds to wait before retrying on 429 SPEED_LIMIT or 503 ODDS_UNAVAILABLE.
Something failed on our side.
object
object
Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.
Valid case-sensitive book keys on INVALID_BOOKMAKER.
403 only: the plan on the presented key.
403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.
Example
{ "error": { "code": "INTERNAL_ERROR", "message": "Something went wrong on our side. It has been logged.", "docs_url": "https://oddslink.app/docs/errors/#internal-error", "request_id": "req_01hz8k4h8n0d4e9f" }}Headers
Section titled “Headers”Requests used this billing period.
Requests remaining this billing period.
What this one call cost against the allowance (0 for a free call).
This plan’s speed limit, in requests per second.
Requests left in the current one-second window.
Seconds until the speed-limit window resets.
This request’s id, for support and for matching against error.request_id.