Use case: alert bots
Odds API for Discord and Telegram alert bots
A line-move bot is three moves on repeat: fetch the prices, compare them with last time, and post whatever shifted far enough to matter. Here is a working one in about thirty lines.
import os
import time
import requests
API = "https://api.sockodds.com/v1/odds"
HEADERS = {"Authorization": f"Bearer {os.environ['SOCKODDS_KEY']}"}
WEBHOOK = os.environ["DISCORD_WEBHOOK_URL"]
MOVE = 0.10 # post when a decimal price moves by ten cents or more
last = {} # (outcome ID, bookmaker) -> last decimal price seen
while True:
r = requests.get(API, headers=HEADERS, timeout=20,
params={"league": "nrl", "markets": "winner"})
if r.status_code == 429:
time.sleep(int(r.headers.get("retry-after", 60)))
continue
r.raise_for_status()
for event in r.json()["data"]:
for book in event["bookmakers"]:
for market in book["markets"]:
for o in market["outcomes"]:
if not o.get("available"):
continue
key = (o["id"], book["key"])
before, now = last.get(key), o["decimal_odds"]
last[key] = now
if before and abs(now - before) >= MOVE:
text = (f'{event["name"]} | {book["name"]} {o["name"]} {before} to {now} '
f'(seen {o["observed_at"][11:16]} UTC)')
requests.post(WEBHOOK, json={"content": text}, timeout=10)
time.sleep(300) # prices refresh about every five minutes
For Telegram, swap the webhook post for the Bot API's sendMessage with your bot token and chat ID. Everything else stays the same.
Design notes
What makes a bot people keep
- Poll at the source's pace. About every five minutes, because prices are re-read about that often, so a faster loop finds nothing new.
- Post moves, not noise. A threshold in cents or in implied percentage keeps the channel readable. Moves on the favourite's side usually matter more than a long shot drifting.
- Say which book and how old. Each price has its own
observed_at; include it, so readers know what they are looking at. - Key on the outcome ID. An outcome has the same ID at every book and on every poll, so the outcome ID and the bookmaker are all the state a bot needs.
- Back off politely. A
429carriesretry-after; sleep that long and carry on. Rejected calls are not billed.
How much quota does a bot use? Each game returned is one object. Watching nine NRL games every five minutes for twelve hours a day comes to about 38,880 objects a month, which fits Rookie. The same nine games around the clock is about 77,760, still inside Rookie; a bot watching every league all day is Pro territory. Polling only on game days, or only from a few hours before kick-off, cuts usage sharply. Try your numbers in the calculator
Questions
Bots and the API
Is there a push or WebSocket option instead of polling?
Pro includes a WebSocket stream at /v1/stream/odds: one event, or up to 20 in a league, sent as a fresh snapshot every 15 seconds, with a heartbeat that costs nothing when nothing changed. It saves you writing a loop but does not make prices any fresher than the five-minute source refresh.
Can the bot run on the free plan?
For building and testing, yes. The free plan's 2,500 objects a month will not last a bot running all day, so plan on Rookie for a bot that runs for real.
Can I alert on player props?
Yes. Add a prop's market key, such as player_disposals_over_under, to markets and the bot watches it for every player. Watch the line as well as the price: books often move the number rather than the odds, and here a new number is a new market, so a line move shows as one line going and another arriving.
Start now
Your first Australian price is one request away.
Free key, no card, AFL and NRL included. Keys are issued on sockodds.com.