Non-Sport Prediction Markets

Non-Sport Prediction Markets

What you'll learn: OpticOdds now covers non-sport prediction markets — elections, economic indicators, crypto price levels, cultural outcomes, and more — from Kalshi and Polymarket. This guide explains what's covered and how to use canonical events to match the same event and market across both platforms, so you can power bots that trade or price across exchanges.

What Are Non-Sport Prediction Markets?

Prediction market platforms like Kalshi and Polymarket list markets on real-world events far beyond sports: "Who wins the FL-20 Democratic primary?", "Will the Fed cut rates in September?", "Will BTC close above $120k on Friday?". OpticOdds ingests these non-sport markets and — critically — matches equivalent events and markets across platforms so you can work with them as one.

Scope: These endpoints return non-sport markets only. Sports prediction markets are handled through the standard OpticOdds sports data flow (/fixtures, /fixtures/odds, etc.) — see the OpticOdds for Prediction Market Makers guide for those. If you're trying to match sports markets across exchanges, these endpoints won't return them.

Categories

Non-sport markets are grouped into a fixed set of categories. Always pull the live list from GET /prediction-markets/categories rather than hardcoding it.

Not every category has events at all times. The full set of categories always exists, but several may be empty depending on what's currently listed across platforms — query each category to see its current coverage. The examples below are illustrative of the kinds of markets each category holds.

CategoryExample markets
politicsUS House/Senate races, international elections, party nominations
financeIndex levels (S&P 500), FX levels (USD/BRL), commodity prices (WTI crude)
cryptoToken price thresholds (e.g. "Bitcoin above ___ by a date")
techProduct launches and approvals (robotaxis, FDA drug approvals, AI benchmarks)
cultureAwards (Emmys), entertainment releases (GTA VI), casting decisions
geopoliticsInternational political events (elections called, relations)
economicsMacro indicators (rate decisions, inflation, jobs)
climateWeather and climate outcomes
healthPublic-health outcomes
companiesCorporate events (M&A, leadership, IPOs)

Available on: Access to these endpoints is enabled per API key. If you receive a 403, contact your OpticOdds representative to have it turned on.

Why Canonical Events?

Every cross-platform prediction market bot — arbitrage, hedging, consolidated pricing — runs into the same wall first: knowing that a Kalshi market and a Polymarket market are the same bet. The two exchanges use different event IDs, different market IDs, different titles, and different market breakdowns for the exact same outcome, so you can't join them on anything the platforms give you.

Canonical events are that join. OpticOdds does the matching across Kalshi and Polymarket for you and hands back shared identifiers you can key on directly:

  • A canonical_id groups the same event across platforms.
  • A canonical_market_id identifies the same outcome across platforms — the same value on Kalshi and Polymarket means "these two markets settle on the same thing."
  • A confidence score (0–1) tells you how sure the match is, per platform.

Feed those shared IDs into your bot and you can line up prices for identical outcomes across exchanges without maintaining your own mapping table.

Supported Platforms

Platformplatform value
Kalshikalshi
Polymarketpolymarket

Key Concepts

canonical_id — The shared event ID

How to read it: A stable OpticOdds identifier for a single real-world event (e.g. "FL-20 Democratic Primary Winner"). Every platform that lists that event is grouped under this one ID.

Why this matters: It's your entry point. List the IDs in a category, then pull the full matched event for each one.

canonical_market_id — The shared outcome ID

How to read it: Within an event, each individual market (each outcome) gets a canonical_market_id. The same canonical_market_id appearing under both Kalshi and Polymarket means those two source markets are the same outcome.

Why this matters: This is the join key your bot uses to pair prices. Match on canonical_market_id, then route orders using each platform's native source_market_id.

confidence — Match reliability

How to read it: A score from 0 to 1 on each matched platform. 1.0 is an exact match; lower values indicate a fuzzier match.

Why this matters: Gate your bot on confidence. For real-money arbitrage you may only want to act on high-confidence matches (e.g. >= 0.95).

Step-by-Step Integration

All requests use the base URL https://api.opticodds.com/api/v3 and require an API key. Pass your key in the X-Api-Key header, not as a ?key= query parameter — keys in URLs leak into server logs, browser history, and proxies.

Step 1: List the categories

Non-sport markets are grouped into categories. Start by pulling the list.

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.opticodds.com/api/v3/prediction-markets/categories"
import requests

r = requests.get(
    "https://api.opticodds.com/api/v3/prediction-markets/categories",
    headers={"X-Api-Key": "YOUR_API_KEY"},
)
categories = r.json()["data"]

Response:

{
  "data": [
    "politics", "economics", "finance", "crypto", "tech", "culture",
    "climate", "health", "geopolitics", "companies"
  ]
}

Step 2: Get the canonical event IDs in a category

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.opticodds.com/api/v3/prediction-markets/canonical-events/ids?category=politics"
r = requests.get(
    "https://api.opticodds.com/api/v3/prediction-markets/canonical-events/ids",
    headers={"X-Api-Key": "YOUR_API_KEY"},
    params={"category": "politics"},
)
ids = r.json()["data"]

Response:

{
  "data": [
    "0084abc100ac5f34988afb271ce21392",
    "00eee8b073cc5a8186937783779206d3",
    "01064646d1d654c5be8c77d1c45ef799"
  ]
}

Tip: Add include_latencies=true to include a latencies object in the response for performance monitoring.

Step 3: Fetch the full canonical event

Pass one or more IDs. canonical_id is repeatable, so you can batch multiple events into a single request.

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.opticodds.com/api/v3/prediction-markets/canonical-events?canonical_id=548068796ec55f2fb280b49a526d9dbe"
r = requests.get(
    "https://api.opticodds.com/api/v3/prediction-markets/canonical-events",
    headers={"X-Api-Key": "YOUR_API_KEY"},
    params={"canonical_id": ["548068796ec55f2fb280b49a526d9dbe"]},
)
event = r.json()["data"][0]

Response:

{
  "data": [
    {
      "canonical_id": "548068796ec55f2fb280b49a526d9dbe",
      "title": "FL-20 Democratic Primary Winner",
      "description": "This market will resolve according to the candidate who wins the nomination for the Democratic Party ...",
      "category": "politics",
      "events": [
        {
          "platform": "kalshi",
          "source_event_id": "KXFLPRIMARY-20D26",
          "confidence": 0.95,
          "markets": [
            { "canonical_market_id": "7106f753fbc75c2a89e6c716e5341359", "source_market_id": "KXFLPRIMARY-20D26-DHOL" },
            { "canonical_market_id": "3b5bf665f0f35a05b1d14552edab5e78", "source_market_id": "KXFLPRIMARY-20D26-DSCH" }
          ]
        },
        {
          "platform": "polymarket",
          "source_event_id": "403518",
          "confidence": 1.0,
          "markets": [
            { "canonical_market_id": "7106f753fbc75c2a89e6c716e5341359", "source_market_id": "2044832" },
            { "canonical_market_id": "3b5bf665f0f35a05b1d14552edab5e78", "source_market_id": "2044836" }
          ]
        }
      ]
    }
  ]
}

Pattern: Pairing a market across Kalshi and Polymarket

Once you have a canonical event, build a lookup keyed on canonical_market_id to pair each outcome across the two platforms.

event = r.json()["data"][0]

pairs = {}  # canonical_market_id -> {platform: source_market_id}
for platform_event in event["events"]:
    platform = platform_event["platform"]
    for m in platform_event["markets"]:
        pairs.setdefault(m["canonical_market_id"], {})[platform] = m["source_market_id"]

# Only outcomes listed on BOTH platforms are actionable for cross-platform strategies
matched = {cid: p for cid, p in pairs.items() if "kalshi" in p and "polymarket" in p}

# matched = {
#   "7106f753fbc75c2a89e6c716e5341359": {"kalshi": "KXFLPRIMARY-20D26-DHOL", "polymarket": "2044832"},
#   "3b5bf665f0f35a05b1d14552edab5e78": {"kalshi": "KXFLPRIMARY-20D26-DSCH", "polymarket": "2044836"},
# }

You now have the native source_market_id on each platform for the same outcome — fetch live prices for each and compare, hedge, or arbitrage.

Endpoint Reference

GET /prediction-markets/categories

Returns the list of categories used to group non-sport canonical events.

Authenticate with the X-Api-Key header (see above). This endpoint takes no query parameters.

GET /prediction-markets/canonical-events/ids

Returns every canonical event ID within a category. Authenticate with the X-Api-Key header (see above).

ParameterRequiredDescription
categoryYesA category from /prediction-markets/categories (e.g. politics).
include_latenciesNoWhen true, adds a latencies object to the response.

GET /prediction-markets/canonical-events

Returns the full canonical event(s): title, description, category, and matched events/markets on each platform. Authenticate with the X-Api-Key header (see above).

ParameterRequiredDescription
canonical_idYesA canonical event ID. Repeatable — pass it multiple times to fetch several events in one call (e.g. &canonical_id=A&canonical_id=B).

Response Fields — Canonical Event

FieldDescription
canonical_idStable OpticOdds ID for the matched event.
titleCanonical event title.
descriptionFull resolution description.
categoryCategory the event belongs to.
events[]One entry per matched platform.
events[].platformSource platform (kalshi, polymarket).
events[].source_event_idThe platform's native event ID (use for order routing).
events[].confidenceMatch confidence, 01.
events[].markets[]Individual markets (outcomes) within the event.
events[].markets[].canonical_market_idShared OpticOdds market ID — the same value across platforms identifies the same outcome. Use it as your join key.
events[].markets[].source_market_idThe platform's native market ID (use for order routing).

Error Responses

StatusBodyCause
400{ "error": "The category parameter is required." }category missing on the IDs endpoint.
400{ "error": "The canonical_id parameter is required." }canonical_id missing on the canonical-events endpoint.
403ForbiddenPrediction-market matching is not enabled on your API key.
401{ "error": "API key is required." }No API key supplied.

Best Practices

  1. Match on canonical_market_id, not on title. Titles differ across platforms; the canonical market ID is the reliable join key.
  2. Filter for outcomes present on both platforms before acting — a market may exist on only one exchange.
  3. Gate on confidence. For real-money strategies, act only on high-confidence matches (e.g. >= 0.95).
  4. Batch your reads. Pass multiple canonical_id values in one call rather than one request per event.
  5. Route with source_market_id / source_event_id. The canonical IDs are for matching; the source IDs are what each platform's own API expects.
  6. Refresh the ID list periodically — new canonical events appear as platforms list new markets.

Glossary

  • Non-sport prediction market — A market on a real-world event outside sports (politics, economics, crypto, etc.), listed by platforms like Kalshi and Polymarket.
  • Canonical event — A single real-world event, matched and grouped across platforms under one canonical_id.
  • Canonical market — A single outcome within a canonical event, identified by a canonical_market_id shared across platforms.
  • Source ID (source_event_id / source_market_id) — A platform's own native identifier, used when calling that platform for prices or placing orders.
  • Confidence — A 0–1 score indicating how reliably a platform's event/markets were matched to the canonical event.


Did this page help you?