tkTickOdds

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);
}