diff --git a/content/en/api-reference/sportsbooks.mdx b/content/en/api-reference/sportsbooks.mdx index af46936..7516f64 100644 --- a/content/en/api-reference/sportsbooks.mdx +++ b/content/en/api-reference/sportsbooks.mdx @@ -436,6 +436,8 @@ The `requires_tier` field indicates the minimum subscription tier needed to acce **Polymarket** and **Kalshi** are prediction market platforms. Unlike traditional sportsbooks, they use binary outcome contracts priced between $0 and $1. SharpAPI normalizes contract prices into standard odds formats (American, decimal, implied probability) so you can compare them directly with sportsbook odds. Kalshi is CFTC-regulated. + +Polymarket rows additionally carry a `polymarketResolution` field reflecting the upstream UMA optimistic-oracle lifecycle (`settled_normal` / `voided` / `disputed` / `proposed` / `unknown`). See [Polymarket Resolution](/concepts/polymarket-resolution) for the per-value semantics and the upstream caveat that cancellation, participant withdrawal, and event-not-occurred all collapse to the single `voided` bucket. ## Sharp vs Soft Books diff --git a/content/en/concepts/_meta.js b/content/en/concepts/_meta.js index 625281d..28658c3 100644 --- a/content/en/concepts/_meta.js +++ b/content/en/concepts/_meta.js @@ -5,4 +5,5 @@ export default { "event-matching": "Event Matching", "live-vs-prematch": "Live vs. Pre-Match", "pinnacle-odds-changed-at": "Pinnacle `odds_changed_at`", + "polymarket-resolution": "Polymarket Resolution", } diff --git a/content/en/concepts/polymarket-resolution.mdx b/content/en/concepts/polymarket-resolution.mdx new file mode 100644 index 0000000..65865d3 --- /dev/null +++ b/content/en/concepts/polymarket-resolution.mdx @@ -0,0 +1,98 @@ +--- +title: "Polymarket Resolution Status" +description: "How SharpAPI surfaces the upstream UMA optimistic-oracle resolution lifecycle on Polymarket markets — settled, voided, disputed, proposed." +--- + +import { Callout } from 'nextra/components' + +# Polymarket Resolution Status + +Polymarket is a prediction-market CLOB whose markets are graded by the [UMA optimistic oracle](https://docs.uma.xyz/), not by a sportsbook trading desk. When you read Polymarket odds through SharpAPI, the row may carry an extra field — `polymarketResolution` — that reflects where that market sits in the UMA resolution lifecycle. + +This field is **Polymarket-only**. Other sportsbook rows (Pinnacle, DraftKings, FanDuel, etc.) do not carry it because their upstream wire formats don't emit an equivalent signal. See [Pinnacle wire survey](https://github.com/Mlaz-code/api-adapters/) for the parallel investigation that concluded the same field cannot be delivered for traditional books. + +## When the field appears + +| Market state | `polymarketResolution` | +|---|---| +| Actively trading | omitted (field not present) | +| Closed, resolved with a winner | `"settled_normal"` | +| Closed, voided / refunded | `"voided"` | +| Closed, UMA dispute in flight | `"disputed"` | +| Closed, UMA proposal submitted, dispute window open | `"proposed"` | +| Closed, lifecycle fields empty (legacy market) | `"unknown"` | +| Any non-Polymarket book | omitted | + +The field is **additive**. Existing parsers that ignore unknown fields will continue to work unchanged. + +## Value semantics + +### `settled_normal` + +The UMA oracle declared a winning outcome. In a binary market, exactly one outcome resolved to `$1.00` and the other to `$0.00`. This is the typical end state. + +```json +{ + "sportsbook": "polymarket", + "marketType": "binary", + "selection": "Yes", + "odds": -10000, + "polymarketResolution": "settled_normal", + "trueProbability": 1.0 +} +``` + +### `voided` + +The UMA oracle voided the market — both binary outcomes resolved to `$0.50` ("refund everyone"). This is the same wire signature for all of: + +- A cancelled match (sporting event cancelled or abandoned) +- A participant withdrawing before the event +- The event never occurring (e.g. "Map 3 winner" when the series ended in 2 maps) +- Any other UMA-determined void + + +**Polymarket does not distinguish *why* a market was voided.** The human-readable reason lives in the off-chain UMA dispute thread on the UMA oracle frontend, not in the Polymarket API. If your application needs to know cancellation-vs-withdrawal-vs-no-event, that information cannot be sourced from Polymarket's wire — you would need to read the UMA dispute body directly. + +This is an intentional design choice from UMA's optimistic-oracle architecture, not a SharpAPI omission. We chose to expose `voided` as a single bucket rather than guess from heuristics — per our [no-inference policy](https://github.com/Mlaz-code/api-adapters/), if upstream is ambiguous, we don't make a guess. + + +### `disputed` + +The UMA proposer submitted a resolution that was challenged. The market is now in a UMA token-holder vote, typically 48 hours. The terminal resolution will eventually become `settled_normal` or `voided` once the vote concludes. + +### `proposed` + +The UMA proposer submitted a candidate resolution; the dispute window is open (typically 2 hours). The market will transition to `settled_normal` / `voided` once the window closes uncontested, or to `disputed` if challenged. + +### `unknown` + +The market is closed but the UMA lifecycle fields are empty. This happens on legacy Polymarket markets that pre-date UMA-status tracking, or on rare edge cases where the Gamma API doesn't surface lifecycle history. The field is `unknown` rather than guessing. + +## Delayed resolution + +Polymarket markets can resolve days or weeks after the underlying event ends. The `polymarketResolution` field appears whenever the upstream resolution lifecycle advances, even long after the market closed. + +If your application processes resolution events (for grading, settlement reconciliation, etc.), watch the SSE stream / WebSocket for these late-arriving rows. + +## Comparison with other books + +| Book | Equivalent field? | Notes | +|---|---|---| +| **Polymarket** | `polymarketResolution` | 5-state enum, derived from UMA oracle | +| **Kalshi** | _(not yet)_ | Kalshi has settlement events but we don't surface them today — separate request | +| **Pinnacle** | _(not available upstream)_ | Pinnacle's wire emits no real-time reason field; `cancellationReason` exists only on the post-grading Lines API partner endpoint | +| **DraftKings / FanDuel / BetMGM / Caesars** | _(not available)_ | Suspended markets simply disappear from the feed; no status field is emitted | +| **OpticOdds (industry comparison)** | _(no reason)_ | Fixture-level `status: cancelled` exists but carries no reason; per-market objects have no status field | + +The data customers want — a per-book settlement reason — is not industry-standard. Polymarket is the rare case where the upstream wire actually carries it, because UMA resolution is on-chain and publicly observable. + +## Why the field is Polymarket-prefixed + +We deliberately named the field `polymarketResolution` rather than a generic `resolutionStatus` so it's obvious the values are Polymarket-specific. A future Kalshi version would be a separate `kalshiResolution` field with its own enum — the wire formats are different enough that a unified enum would either be lowest-common-denominator (useless) or full of asterisks for "Polymarket-only" / "Kalshi-only" values. + +## See also + +- [Sportsbook list — prediction markets](/api-reference/sportsbooks#prediction-markets) +- [Odds API reference](/api-reference/odds) +- [Live vs. Pre-Match](/concepts/live-vs-prematch) — covers the related `marketStatus` semantics