Get a free key

Use case: prediction markets

Prediction market odds API: Kalshi and Polymarket beside the bookmakers

Kalshi and Polymarket now price plenty of the same games as the bookmakers. In this feed they are not a separate product: they appear as two more bookmakers in the response, on the same events and the same outcome IDs, converted to the same price format.

How it fits

Two more keys, same shape

Read the kalshi and polymarket entries exactly as you would sportsbet or tab: a decimal price, its implied probability, an available flag and the time it was seen. /v1/bookmakers lists them with kind: prediction_market. They appear wherever the venues list a fixture the feed covers, which leans toward the most heavily traded leagues and events.

Prediction markets trade contracts that pay one dollar if something happens. A contract at 62 cents implies a 62% chance, the same as a decimal price of about 1.613, before any trading fee. The feed does that conversion for you, so the comparison is like for like.

decimal ≈ 1 ÷ contract price   (0.62 → 1.613)

Why compare

What the gap can tell you

  • A second opinion. Prediction markets are set by traders, not a bookmaker's margin, which makes them a useful cross-check on a fair price.
  • Venue gaps. When a book and a prediction market disagree by more than the fees, one of them is out of line.
  • Research. How the two kinds of market move into kick-off is an open question, and you can record it from one feed.

Code

Compare venues on one market

This prints each prediction market's head to head price for the home side next to the best bookmaker price, and the gap between them.

venues.py
import os
import requests

VENUES = {"kalshi", "polymarket"}

resp = requests.get(
    "https://api.sockodds.com/v1/odds",
    params={"league": "nfl", "markets": "winner"},
    headers={"Authorization": f"Bearer {os.environ['SOCKODDS_KEY']}"},
    timeout=20,
)
resp.raise_for_status()

for event in resp.json()["data"]:
    home = {}  # bookmaker -> decimal price on the home side, whole game
    for book in event["bookmakers"]:
        for market in book["markets"]:
            for o in market["outcomes"]:
                if market["key"] == "winner" and market["period"] == "full" and o["side"] == "home" and o.get("available"):
                    home[book["key"]] = o["decimal_odds"]
    venues = {b: p for b, p in home.items() if b in VENUES}
    books = {b: p for b, p in home.items() if b not in VENUES}
    if not venues or not books:
        continue
    best = max(books, key=books.get)
    for venue, price in venues.items():
        gap = books[best] / price - 1
        print(f'{event["name"]}: {venue} {price} vs {best} {books[best]} ({gap:+.1%})')

Read the gap with care.

  • Prediction markets charge trading fees and have a spread between buy and sell. A small gap is often just those costs.
  • The two can define a market differently, for example whether overtime counts. Check that both sides settle on the same thing before treating them as equal.
  • Whether you can trade on a prediction market depends on where you live. The feed shows prices; it does not grant access to any venue.
Which plans include Kalshi and Polymarket?

Pro, which includes every bookmaker and venue with no cap.

Do they cover Australian sports?

Coverage follows what each venue lists, which leans toward the most heavily traded leagues. An event's bookmakers list shows whether either venue priced it.

Can I use them in a fair price?

Yes. They sit in the same response as everything else, on the same outcome IDs, so you can build your own fair price with or without them. The fair odds page shows the methods.

Start now

Your first Australian price is one request away.

Free key, no card, AFL and NRL included. Keys are issued on sockodds.com.