Quickstart
Set up your account, create one key, then make your first metered odds request. Want to see a real response before signing up? Try it now runs five free requests a day with no key, and the live board shows a sample slate with no login at all.
1. Create your account
Create an account. If asked to confirm your email, use the link we send and then sign in. Otherwise, you are signed in immediately. Creating and managing keys uses that signed-in session. Your API key is for API requests only; it cannot manage your account.
2. Create and save a key
In Account, create a live key and copy its secret immediately. The createApiKey operation returns the full secret once, and it cannot be shown again. See Authentication for the two authentication modes.
3. Request odds
Copy the generated request below, replace the placeholder with the key you just saved, then run it. The sample uses soccer narrowed to the Premier League. Sport keys are lowercase: common US leagues use compact keys such as nfl and mlb. soccer and tennis return every currently available competition; add ?league=epl or ?tournament=atp_hangzhou to narrow either aggregate key. An aggregate response can be larger and may take longer. Existing keys such as epl and tennis_atp_hangzhou remain supported; tennis keys come and go week to week, so list GET /v1/sports rather than hard-coding one. See Sport keys. The key travels in the X-API-Key header.
/v1/sports/soccer/odds?league=epl&markets=h2h,spreadscurl --request GET \
--url "https://oddslink.app/v1/sports/soccer/odds?league=epl&markets=h2h,spreads" \
--header "X-API-Key: ok_live_..." \
--compressedimport requests
import json
resp = requests.get(
"https://oddslink.app/v1/sports/soccer/odds",
params={"league": "epl", "markets": "h2h,spreads"},
headers={"X-API-Key": "ok_live_..."},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(json.dumps(data, indent=2))async function main() {
const res = await fetch(
"https://oddslink.app/v1/sports/soccer/odds?league=epl&markets=h2h,spreads",
{ headers: { "X-API-Key": "ok_live_..." } }
);
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://oddslink.app/v1/sports/soccer/odds?league=epl&markets=h2h,spreads", nil)
req.Header.Set("X-API-Key", "ok_live_...")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$ch = curl_init("https://oddslink.app/v1/sports/soccer/odds?league=epl&markets=h2h,spreads");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_HTTPHEADER => ["X-API-Key: ok_live_..."],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);[
{
"id": "soccer:crystalpalace-nottinghamforest:2026-10-11",
"sport_key": "soccer",
"sport_title": "Soccer",
"commence_time": "2026-10-11T13:00:00.000Z",
"is_live": false,
"status": "scheduled",
"home_team": "Crystal Palace",
"away_team": "Nottingham Forest",
"bookmakers": [
{
"key": "betmgm",
"title": "BetMGM",
"link": "https://sports.nj.betmgm.com/en/sports/events/crystal-palace-nottingham-forest-2:7865814",
"last_update": "2026-10-10T22:06:51.003Z",
"markets": [
{
"key": "spreads",
"last_update": "2026-10-10T22:06:51.003Z",
"outcomes": [
{
"name": "Nottingham Forest",
"price": 145,
"point": -0.5,
"main": true
},
{
"name": "Crystal Palace",
"price": -210,
"point": 0.5,
"main": true
}
]
}
]
}
],
"unmatched_bookmakers": []
}
]4. Read the response
Each fixture's bookmakers[] carries that book's markets[], and each market carries outcomes[]. unmatched_bookmakers names every book that returned no markets for the fixture in this response: every book you asked for with bookmakers=, or every catalogue book when you pass none (props use the props-capable catalogue books). The listOdds operation counts as one request against your plan's monthly allowance, regardless of how many fixtures or books the response contains.
One game, two books
Books describe the same game differently. Here is how two of them might send the same Eagles game: different team names, different time formats, home team in a different place, and one lists five spreads with no sign of which is the main line.
// Book A
{ "event": "PHI Eagles vs DAL Cowboys", "start": "11/08 4:25PM ET",
"spread": [ { "line": "-3.5", "odds": "-110" }, { "line": "-2.5", "odds": "-135" },
{ "line": "-4.5", "odds": "+105" }, { "line": "-1.5", "odds": "-160" },
{ "line": "-5.5", "odds": "+125" } ] }
// Book B
{ "home": "Philadelphia", "away": "Dallas", "kickoff": 1794173100,
"lines": { "hcp_home": -3.5, "hcp_home_price": 1.92, "hcp_away_price": 1.95 } }The API turns both into one fixture with one id. Team names, times and market shapes are the same for every book, and main: true marks each book's main line, so you can compare books outcome by outcome without matching anything yourself. Request spreads explicitly and the alternate lines come too, marked main: false; see Main line and ladders.
{
"id": "nfl:dallascowboys-philadelphiaeagles:2026-11-08",
"commence_time": "2026-11-08T21:25:00.000Z",
"home_team": "Philadelphia Eagles",
"away_team": "Dallas Cowboys",
"bookmakers": [
{ "key": "draftkings", "title": "DraftKings",
"markets": [ { "key": "spreads", "outcomes": [
{ "name": "Philadelphia Eagles", "price": -110, "point": -3.5, "main": true },
{ "name": "Dallas Cowboys", "price": -110, "point": 3.5, "main": true } ] } ] },
{ "key": "fanduel", "title": "FanDuel",
"markets": [ { "key": "spreads", "outcomes": [
{ "name": "Philadelphia Eagles", "price": -109, "point": -3.5, "main": true },
{ "name": "Dallas Cowboys", "price": -105, "point": 3.5, "main": true } ] } ] }
]
}That is the first-response loop: a signed-in account, a key you saved once, a sport key, and a markets list. The Odds guide covers markets and periods, sizes and formats; the History guide covers the other implemented endpoint family.