Overview
Predexon’s sports discovery API provides a unified cross-venue view of sports betting markets. A single “game” surfaces every venue that lists that game, with each venue’s native market data (prices, volume, liquidity, outcomes) nested underneath.
Data is sourced from:
- Polymarket
- Kalshi
- Limitless
- Opinion
- Predict.fun
All endpoints are served under /v2/sports/* and require your data key in the x-api-key header. (The trading key used by the Order Router on trade.predexon.com is a separate credential.)
Data Model
The structure below describes the per-venue response from GET /v2/sports/markets. For a compact game/outcome list, see GET /v2/sports/games.
Game
A game is a single real-world sporting event (e.g. “Atlanta Hawks vs. New York Knicks on April 18, 2026”). Predexon identifies each game with a canonical game_id of the form:
{league}-{team_code_a}-{team_code_b}-{YYYY-MM-DD}
Example: nba-atl-nyk-2026-04-18
Team codes are sorted alphabetically to guarantee the same two teams on the same date always produce the same game_id - regardless of which venue is the source.
game_id is the broad sports fixture. It is separate from event_id, which identifies the canonical market/question scope attached to that game. For the current sports v1, only game_winner markets are exposed, so game_id and event_id often have the same value. Future spreads, totals, and props can share a game_id while using more specific event_id values.
Market Types
Each game has one or more market_types, representing the kind of bet being placed. Today the only supported type is:
| Market Type | Description |
|---|
game_winner | Bet on which team wins the game |
Future additions (game_spread, game_total_points, etc.) will appear as additional entries under a game’s market_types array.
Venue Blocks
Under each market_type, each venue that lists that market appears as its own venue block. Venue blocks contain:
- Venue-native identifiers (
market_id, market_slug, condition_id)
- Live market-level metadata (
market_title, volume, liquidity, end_time)
- An array of
outcomes specific to that venue
Identifier fields are venue-specific. Kalshi uses tickers and has no condition_id or market_slug, so those fields are omitted from Kalshi venue blocks. Polymarket, Limitless, and Predict.fun all use on-chain condition_ids. Opinion uses a numeric market_id.
Outcomes
Each venue block has an outcomes array listing the individual tradeable sides of that market. Every outcome includes:
| Field | Description |
|---|
outcome | Canonical outcome code (team code like "atl", or "draw") |
outcome_label | Human-readable label ("Atlanta Hawks", "Draw") |
event_id | Canonical market/question identifier. For current game_winner rows this often equals game_id. |
condition_id | On-chain condition ID for this outcome’s market (Polymarket/Limitless/Predict only) |
market_slug | Venue-native slug for this outcome’s market |
market_id | Venue-native identifier (Kalshi ticker / Opinion integer only) |
tokens | YES and NO sides with prices and identifiers (see below) |
Tokens & Prices
Each outcome has a tokens object with side entries. Prices live on the token side, not on the outcome. Most current sports v1 listings expose the tradable yes side for each canonical outcome; no may be omitted or empty when the venue/listing does not expose a distinct routable NO side in the canonical sports projection.
| Field | Description |
|---|
tokens.yes.price | Current YES-side price (0.0 - 1.0). The cost to bet FOR this outcome. null if unpriced. |
tokens.yes.token_id | Venue-native token ID for the YES side. Present for on-chain venues (Polymarket, Limitless, Predict, Opinion). Not present for Kalshi (Kalshi has no on-chain tokens). |
tokens.yes.predexon_id | Predexon canonical outcome ID. Present on routable listings. Use for routing and outcome lookup. |
tokens.no.price | Current NO-side price (0.0 - 1.0). The cost to bet AGAINST this outcome. null if unpriced. |
tokens.no.token_id | Venue-native token ID for the NO side. Same presence rules as YES. |
tokens.no.predexon_id | Predexon canonical outcome ID for a distinct NO listing when exposed. May be omitted. |
yes.price + no.price may not equal 1.0 — the spread represents the venue’s bid-ask spread or overround. For venues where only one side has been quoted, the other side may be null.
predexon_id
A predexon_id is Predexon’s canonical identifier for one tradeable outcome, not a venue-native token. The same outcome across venues shares the same predexon_id.
Example: if Kalshi, Polymarket, and Predict.fun all list “Arizona Diamondbacks win” for the same game, each venue listing returns the same canonical predexon_id.
Use predexon_id for order routing, orderbook subscriptions, and as the key for cross-venue outcome lookups via GET /v2/sports/outcomes/{predexon_id}.
Identifier cleanup:
| Field | Meaning |
|---|
predexon_id | Canonical Predexon outcome ID shared across matched venues. |
game_id | Broad real-world sports game. |
event_id | Canonical market/question scope attached to a game. |
token_id | Venue-native executable token/side ID where applicable. |
market_id | Venue-native market ID where the venue has one. |
market_ticker | Kalshi ticker. |
condition_id | CTF condition ID, not an outcome ID. |
Cross-Venue Matching
The same outcome on different venues shares the same canonical predexon_id. To find all executable venue listings for a given outcome:
GET /v2/sports/outcomes/px-uvtpjis2k7bj
Returns every venue listing for that canonical outcome, including venue-native identifiers like Kalshi tickers, Polymarket condition IDs, and token IDs.
Matching is performed deterministically using team code mappings curated by Predexon. No LLMs or probabilistic matching - if two venues list the same team on the same date, they match.
Live Game State
Live scores and game state are exposed separately from market discovery:
| Endpoint | Purpose |
|---|
GET /v2/sports/live | List live-state snapshots by game_id. |
GET /v2/sports/live/{game_id} | Fetch one live-state snapshot. |
Live state keys off game_id, the broad real-world game. It does not key off event_id, because future spreads, totals, and props can all belong to the same game while using different canonical market/question IDs.
When live state is not yet available for a game, the endpoint can still return a game shell with reliability.state = "no_data" and null score fields. Source-level snapshots are available with include_sources=true.
See Sports Live State for reliability semantics and the websocket update shape.
Dates & Times
game_date
The calendar date of the game in its sport’s primary local region:
- US sports (NBA, NHL, MLB, NFL, CFB, MLS): Eastern Time (ET)
- European football (EPL, La Liga, Serie A, Ligue 1, Bundesliga, UCL, UEL, etc.): UTC
This matches the convention used by the venues’ own slugs. A late-night Lakers game on Apr 15 PT will be labeled 2026-04-15 (not April 16) because ET is the reference.
Format: YYYY-MM-DD.
game_date_timezone
Game objects returned by /v2/sports/markets include a game_date_timezone field indicating which timezone game_date refers to. Possible values: "US/Eastern" or "UTC".
Use this to correctly interpret game_date and the game_date, game_date_from, and game_date_to query filters. For example, an NBA game at 10:30 PM ET on April 23 has game_date: "2026-04-23" and game_date_timezone: "US/Eastern" — even though in UTC it’s already April 24.
When filtering by game_date, pass dates in the sport’s local timezone, not UTC. For NBA games, use the Eastern Time date. For EPL games, use the UTC date. The game_date_timezone field on /v2/sports/markets responses tells you which convention applies.
end_time
The timestamp when the venue’s market stops accepting trades. This is typically around game start but can be earlier (pre-game lock) or later (some venues keep markets open during live events).
Format: ISO-8601 with UTC offset, e.g. 2026-04-18T22:00:00+00:00.
end_time semantics vary slightly per venue:
- Polymarket: market close time (
endDate)
- Kalshi:
close_time
- Opinion:
cutoffAt
- Limitless: not currently indexed - returned as
null
- Predict.fun: not currently indexed - returned as
null
Venue Coverage
Not every venue lists every sport. Current coverage:
| League | Code | Polymarket | Kalshi | Limitless | Opinion | Predict.fun |
|---|
| NBA | nba | ✓ | ✓ | - | ✓ | ✓ |
| NHL | nhl | ✓ | ✓ | - | - | ✓ |
| MLB | mlb | ✓ | ✓ | - | - | ✓ |
| MLS | mls | ✓ | ✓ | - | - | - |
| Premier League | epl | ✓ | ✓ | ✓ | ✓ | ✓ |
| Serie A | sea | ✓ | ✓ | ✓ | ✓ | ✓ |
| La Liga | lal | ✓ | ✓ | ✓ | ✓ | ✓ |
| Ligue 1 | fl1 | ✓ | ✓ | ✓ | ✓ | ✓ |
| Bundesliga | bun | ✓ | ✓ | ✓ | - | ✓ |
| Champions League | ucl | ✓ | ✓ | ✓ | - | - |
| Europa League | uel | ✓ | ✓ | ✓ | - | - |
| Eredivisie | ere | ✓ | ✓ | - | - | - |
| Brasileirao | bra | ✓ | ✓ | - | - | - |
This matrix reflects current coverage and will change as venues add or drop leagues. Use GET /v2/sports/categories for the live, always-up-to-date list.
2-way vs 3-way Markets
2-way (US sports)
NBA, NHL, NFL, MLB, CFB games have two outcomes: Team A wins or Team B wins. Each venue block contains exactly 2 outcomes.
Example outcomes array for an NBA game on Polymarket:
[
{
"outcome": "atl",
"outcome_label": "Atlanta Hawks",
"condition_id": "0xc3b0...",
"market_slug": "nba-atl-nyk-2026-04-18",
"tokens": {
"yes": { "token_id": "17221...", "predexon_id": "px-uvt...", "price": 0.33 },
"no": { "token_id": "98267...", "predexon_id": "px-xcu...", "price": 0.67 }
}
},
{
"outcome": "nyk",
"outcome_label": "New York Knicks",
"condition_id": "0xc3b0...",
"market_slug": "nba-atl-nyk-2026-04-18",
"tokens": {
"yes": { "token_id": "98267...", "predexon_id": "px-xcu...", "price": 0.67 },
"no": { "token_id": "17221...", "predexon_id": "px-uvt...", "price": 0.33 }
}
}
]
EPL, Serie A, La Liga, Ligue 1, Bundesliga, UCL, UEL, etc. have three outcomes: Team A wins, Team B wins, or Draw. On Polymarket and Predict.fun, each outcome is a separate on-chain market (different condition_id per outcome) - Predexon aggregates them into a single venue block so the consumer doesn’t need to deal with this venue-native complexity.
Example outcomes array for an EPL game on Limitless:
[
{
"outcome": "bou",
"outcome_label": "Bournemouth",
"condition_id": "0xaaa...",
"market_slug": "bournemouth-177...",
"tokens": {
"yes": { "token_id": "123...", "predexon_id": "px-...", "price": 0.28 },
"no": { "token_id": "456...", "predexon_id": "px-...", "price": 0.72 }
}
},
{
"outcome": "draw",
"outcome_label": "Draw",
"condition_id": "0xbbb...",
"market_slug": "draw-177...",
"tokens": {
"yes": { "token_id": "789...", "predexon_id": "px-...", "price": 0.25 },
"no": { "token_id": "012...", "predexon_id": "px-...", "price": 0.75 }
}
},
{
"outcome": "new",
"outcome_label": "Newcastle",
"condition_id": "0xccc...",
"market_slug": "newcastle-177...",
"tokens": {
"yes": { "token_id": "345...", "predexon_id": "px-...", "price": 0.48 },
"no": { "token_id": "678...", "predexon_id": "px-...", "price": 0.52 }
}
}
]
Venue-level fields (volume, liquidity) are summed across the 3 underlying markets. end_time is the latest of the 3.
Data Freshness
- Game structure (which games exist, which venues cover them): updated in near real-time as venues list new markets.
- Prices, volume, liquidity: read live from each venue’s indexer state table on every request. Lag is typically sub-second.
- End times, titles, labels: populated at ingestion time; updated when the venue publishes metadata changes.
Responses are cached for 60 seconds by default to protect venue databases under load. Trading decisions requiring fresher data should consult the venue’s orderbook endpoints directly.
See Also
The predexon_id values returned by the discovery endpoints are the input to the Order Router. Pass the canonical predexon_id, and the router executes across every routed venue that lists the same outcome.