Examples
Common integration patterns in Python, JavaScript, and curl.
Fetch today's Premier League matches
Python
import requests
HEADERS = {"X-API-Key": "YOUR_KEY"}
BASE = "https://api.tickodds.com/api/v1"
r = requests.get(
f"{BASE}/competitions/soccer/england-premier-league/matches",
params={"upcoming": 1},
headers=HEADERS,
)
for match in r.json()["data"]:
print(match["home"], "v", match["away"], "@", match["kickoff"])Node.js
const res = await fetch(
"https://api.tickodds.com/api/v1/competitions/soccer/england-premier-league/matches?upcoming=1",
{ headers: { "X-API-Key": "YOUR_KEY" } }
);
const { data } = await res.json();
for (const match of data) {
console.log(match.home, "v", match.away);
}Stream live scores
Node.js (using ws package)
import WebSocket from "ws";
const ws = new WebSocket(
"wss://api.tickodds.com/ws/live?apiKey=YOUR_KEY"
);
ws.on("open", () => {
ws.send(JSON.stringify({ subscribe: ["Soccer"] }));
});
ws.on("message", (raw) => {
const msg = JSON.parse(raw);
if (msg.type === "update" && msg.change === "score") {
const e = msg.event;
console.log(`${e.home} ${e.score} ${e.away} @ ${e.clock}`);
}
});Python (websockets)
import asyncio, json, websockets
async def main():
url = "wss://api.tickodds.com/ws/live?apiKey=YOUR_KEY"
async with websockets.connect(url) as ws:
await ws.send(json.dumps({"subscribe": ["Soccer"]}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "update" and msg["change"] == "score":
e = msg["event"]
print(f"{e['home']} {e['score']} {e['away']} @ {e['clock']}")
asyncio.run(main())Read odds with canonical fields
Selections carry a canonical side (home, away, draw, over, under, yes, no) and numeric line — so you don't need to pattern-match display names.
const match = await fetch(
"https://api.tickodds.com/api/v1/matches/191691460",
{ headers: { "X-API-Key": "YOUR_KEY" } }
).then(r => r.json());
// Option A: via the typed marketGroups[]
const ou = match.data.marketGroups.find(g => g.key === "over_under_2_5");
const over = ou.selections.find(s => s.side === "over");
const under = ou.selections.find(s => s.side === "under");
console.log("Over:", over.odds, "line:", over.line);
// Option B: via the flat odds[] view — easier for aggregation
const rows = match.data.odds.filter(
o => o.industryKey === "totals" && o.period === "full_game" && o.line === 2.5
);
for (const row of rows) console.log(row.side, row.price);Cross-book compatibility (industryKey)
Every market group carries an industryKey that matches the key The Odds API / OpticOdds use, so you can pipe our output into tooling built for those feeds. Period markets are suffixed: h2h_h1, totals_q1, spreads_h1.
// All main moneyline / spread / totals rows, full-game only
const mains = match.data.odds.filter(o =>
["h2h", "h2h_3_way", "spreads", "totals"].includes(o.industryKey) &&
o.period === "full_game" &&
o.isMain
);
// Pair home/away spreads via groupingKey
const byGroup = new Map();
for (const row of match.data.odds) {
if (row.industryKey !== "spreads") continue;
if (!byGroup.has(row.groupingKey)) byGroup.set(row.groupingKey, []);
byGroup.get(row.groupingKey).push(row);
}