{"openapi":"3.1.0","info":{"title":"Polymarket Data API v2","description":"The Polymarket Data API: wallet portfolios, trade and activity feeds, market state and ranked boards.\n\n## Conventions every endpoint shares\n\n- **Envelope**: every response wraps its payload in `data` (paged routes add `pagination`). A documented miss is `data: null` or an empty list, never an error.\n- **Pagination is cursor-only**: follow `pagination.next_cursor` until `null`; `has_more` is exact, and there is no `offset` query parameter (sending one is a `400`). Cursors are signed, typed per endpoint, and opaque. The feeds (`trades`, `activity`, combo activity) are keyset walks, stable across concurrent writes; the boards, `holders` and most combo-position sorts are offset walks behind the opaque token, so a page taken across a data refresh can skip or repeat rows. Where a cursor binds its cohort (the boards, positions, combo positions), resuming bare is fine, restating the same values is fine, and contradicting them is a `400`. The `trades`/`activity` feed cursors carry only the seek anchor and page size (plus the sort direction on activity): re-send identical filters on every page, because changing one mid-walk re-anchors silently.\n- **Rate limiting**: `429` with `Retry-After` is the busy signal for heavy queries and pool saturation. A heavy query may first be queued briefly for a capacity slot; the `429` arrives only if that short wait ends unserved. Each caller also has a per-client request allowance, and bursts past it get the same `429` with `Retry-After` sized to the remaining wait. Retry after the given delay.\n- **Identifiers**: `condition` (aliases `condition_id`, `conditionId`) is the unified query key for on-chain 0x condition ids; `market_id` fields carry Gamma's own market ids; `event_id` takes Gamma event ids; `token_id` is the CLOB asset id (the key on `/v2/prices-history`).\n- **Params** accept both snake_case and camelCase spellings.\n- **Units**: bare `volume`/`size` values are **shares**; `_usdc` suffixed fields are USD; `taker_` prefixed volumes are one-side.\n- **Sentinels**: `outcome_index: 999` means the outcome could not be labeled; a missing or `null` numeric field means unavailable, never zero.\n- **Windows on `/v2/trades?user=` and `/v2/activity`**: an omitted or `0` `start` floors to three years back (`start=1` asks for full history); an omitted or `0` `end` is now plus one day. The other `/v2/trades` shapes ignore `start`/`end`: `condition`/`event_id` serve a fixed three-year window and the bare feed serves the rolling current-plus-previous month. Other windowed routes treat omitted/`0` bounds as unbounded; each documents its own rule. `/v2/prices-history` is the strict one, where a `0` bound is a `400`.\n- **Auth**: data routes take a bearer token in `Authorization` (the `AUTH_TOKEN` header is accepted as an alias).","contact":{"name":"Polymarket"},"license":{"name":"MIT","identifier":"MIT"},"version":"0.1.0"},"servers":[{"url":"https://data-api.polymarket.com","description":"Production"},{"url":"https://data-api-rs.stage.pmd.use1.polymarket.sh","description":"Staging"}],"paths":{"/v2/activity":{"get":{"tags":["feeds"],"summary":"List account activity","description":"Keyset-paginated activity feed (trades, splits, merges,\nredeems, …) in the standard `{ data, pagination }` envelope.\n\nOrdering is `(block_timestamp, sequence_id)`, `DESC` by default or `ASC` via\n`sort_direction=ASC`; both keyset-seekable. Value sorts (`CASH`/`TOKENS`)\nhave no seek anchor and are rejected with `400` rather than silently\nre-served as page one. The cursor binds the direction it was minted under\nand the resume ADOPTS it, so a replay cannot flip the walk mid-stream.\n\nA malformed `condition` id is a `400` naming the value; a\nwell-formed one that matches nothing serves an empty `data` array, which\nis the meaningful zero-state; absence means the market is not servable,\nand only that.","operationId":"get_activity","parameters":[{"name":"user","in":"query","description":"Required; the feed is user-anchored.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"Page size; default 100, max 1000, past-cap rejected.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque cursor from a prior response's `next_cursor`; binds the sort\ndirection it was minted under.","required":false,"schema":{"type":["string","null"]}},{"name":"type","in":"query","description":"Activity type(s), comma-separated (TRADE, SPLIT, MERGE, REDEEM, …).\n\n`TIP` is **opt-in**: it is never in the default set, so it is only\nreturned when you name it here. A tip is a user↔user pUSD transfer that\nis not a trade-settlement leg; `size` is the amount and `side` carries the\ndirection (`IN` received / `OUT` sent).","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Condition id(s), comma-separated (at most 20 distinct values).\n`condition_id` / `conditionId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}},{"name":"event_id","in":"query","description":"Gamma event id(s), comma-separated; resolves to the events' markets.\nMutually exclusive with `condition`.","required":false,"schema":{"type":["string","null"]}},{"name":"side","in":"query","description":"BUY or SELL.","required":false,"schema":{"type":["string","null"]}},{"name":"start","in":"query","description":"Window start on `block_timestamp`, epoch seconds (inclusive). Omitted\nor `0` floors to three years back; pass `start=1` for full history.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"end","in":"query","description":"Window end, epoch seconds (inclusive); omitted or `0` means now plus\none day.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"sort_by","in":"query","description":"Only `TIMESTAMP` is supported (v2 pages by keyset).","required":false,"schema":{"type":["string","null"]}},{"name":"sort_direction","in":"query","description":"`ASC` or `DESC` (default). The keyset seeks in the chosen direction;\nthe minted cursor binds it, so pass it consistently when paging.","required":false,"schema":{"type":["string","null"]}},{"name":"exclude_deposits_withdrawals","in":"query","description":"Defaults to `true`.","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"A page of activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityPage"}}}},"400":{"description":"Missing `user`, invalid query params, unsupported sort, bad cursor, a malformed 'condition' id, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/activity/combos":{"get":{"tags":["feeds"],"summary":"List combo activity","description":"Keyset-paginated combo lifecycle + redemption\nfeed for a user, in the standard `{ data, pagination }` envelope.\n\nPass `?cursor=` from a prior response's `next_cursor` to fetch the next page.\nUnlike the activity feed, the anchor behind the cursor is\n`(block_number, log_index)`; this endpoint's total order.\n\nA malformed `condition` combo condition id is a `400` naming the value; a\nwell-formed one that matches nothing serves an empty `data` array, which\nis the meaningful zero-state.","operationId":"get_combos","parameters":[{"name":"user","in":"query","description":"Required; the feed is user-anchored.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Combo condition id(s), comma-separated (at most 20 distinct values).\n`condition_id` / `conditionId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of combo activity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboActivityPage"}}}},"400":{"description":"Invalid query params or cursor, a malformed 'condition' combo id, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/approvals":{"get":{"tags":["wallet"],"summary":"Get wallet approvals","description":"Polygon token/operator approval state for one wallet.\n\n`?user=` must be an EVM address. The complete served catalog is returned in\ncanonical order under `{ data }`; this endpoint is not paginated.","operationId":"get_approvals","parameters":[{"name":"user","in":"query","description":"The proxy wallet whose approval state to return. Required EVM address.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Approval state for the wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_Approvals"}}}},"400":{"description":"Missing or invalid 'user' address, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/biggest-winners":{"get":{"tags":["boards"],"summary":"List the biggest wins","description":"The biggest single winning positions.\n\nOne row per winning POSITION, not per user: `pnl` is\n`final_value - initial_value` for that position, and the window\n(`?time_period=`, default `day`) is on when it resolved. `?category=`\nnarrows to a market category. Deeper pages come only from `?cursor=`,\nwhich **pins the window and category it was minted on**; restating a\ndifferent one is a `400`, not a silent re-point.\n\nCombo wins are first-class rows here, tagged `kind = \"combo\"`. They carry a\n`' / '`-joined title of their legs and no Gamma event; `event_id` is `0`\nand `event_slug` empty; so **branch on `kind` before building an event\nlink**.","operationId":"get_biggest_winners","parameters":[{"name":"time_period","in":"query","description":"Window on `resolved_at`: `day` | `week` | `month` | `all`. Defaults to `day`.","required":false,"schema":{"type":["string","null"]}},{"name":"category","in":"query","description":"`overall` (default), a Gamma market category (e.g. `sports`), or a\nsynthetic category: `combos` (combinatorial wins get their own full\ntop-500 per window) or `esports` (promoted subcategory).","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of the biggest winning positions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiggestWinnersPage"}}}},"400":{"description":"Invalid time_period or cursor, or a param that contradicts the cursor pin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/builders/leaderboard":{"get":{"tags":["boards"],"summary":"Get the builders leaderboard","description":"The ranked board of builders by volume.\n\n`?time_period=` is `day` (default), `week`, `month` or `all` and selects the\n**window**; one row per builder in it. Deeper pages come only from\n`?cursor=`.\n\nA cursor **pins the window it was minted on**, so following it needs no\n`?time_period=`; and passing a different one is a `400` rather than a\nsilent re-point, since an offset from one board means nothing on another.\n\n`volume` is in SHARES, not USDC, the same unit as `/v2/leaderboard`'s\n`volume`. `active_users` counts distinct makers in the window.\n\n`builder` is a display name that falls back to `builder_code` for a builder\nwith no profile, so key on `builder_code` and render `builder`.","operationId":"get_builders_leaderboard","parameters":[{"name":"time_period","in":"query","description":"Window: `day` | `week` | `month` | `all`. Defaults to `day`.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of the builders board","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildersLeaderboardPage"}}}},"400":{"description":"Invalid time_period or cursor, or a time_period that contradicts the cursor's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/builders/volume":{"get":{"tags":["boards"],"summary":"Get builder volume over time","description":"The per-builder volume time series.\n\n`?interval=` is the **bucket width**, not a window: `day` (default) returns\nevery day on record bucketed daily, `week` and `month` bucket accordingly,\nand `all` buckets by calendar YEAR. `?limit=` bounds how many of the most\nrecent buckets come back (default 30); buckets, not rows, so a period is\nnever returned half-populated. `timePeriod` is accepted as an alias for\n`interval`.\n\n`rank` is the builder's placing **within its own bucket**, so it moves along\nthe series. `volume` is in SHARES; see `/v2/builders/leaderboard`.\n\nNot paginated: `data` is the array with no `pagination`, the `/v2/oi` shape.\nRows arrive newest bucket first, ranked within each.","operationId":"get_builders_volume","parameters":[{"name":"interval","in":"query","description":"Bucket width: `day` | `week` | `month` | `all`. Defaults to `day`.\n`timePeriod` and `time_period` are accepted aliases.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"How many of the most recent buckets to return. Defaults to 30, capped at\n90; a lower ceiling than the rest of the surface, because only ~308\ndaily buckets exist and the family maximum would return the whole series.\n\nBounds BUCKETS, not rows: a row limit would cut a bucket in half and\nleave a partial period in the series.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":90,"minimum":0}}],"responses":{"200":{"description":"The volume series for the requested interval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_Vec_BuilderVolumePoint"}}}},"400":{"description":"Invalid interval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/holders":{"get":{"tags":["markets"],"summary":"List a market's top holders","description":"Top holders of a market, netted per user and grouped by\noutcome token.\n\n`?condition=` (CSV of `condition_id`) is required (400 otherwise). `?limit=`\n(default 100, max 1000; v2 family-uniform) sizes the page **per outcome\ntoken**; `?min_balance=` filters the served amount.\n\n`?include_pnl=true` opts each holder row into the position economics\n(entry price and cost, current price and value, realized, unrealized and\ntotal profit) and switches the amounts to per-side gross balances, so a\nwallet holding both outcomes appears under both tokens. The default\nresponse is unchanged. This mode serves one market's table at a time:\nexactly one `condition` and `limit` at most 100 (400 otherwise, including\nvia a cursor that carries a wider window).\n\nA malformed condition id is a `400` naming the value; a well-formed one\nthat resolves to no holdings serves an empty `data` array, which is the\nmeaningful zero-state.\n\nDeeper pages come only from `?cursor=` (which carries the page window and\noverrides `limit`).\n\nPage walks advance every token group together, so a group leaves `data`\nonce its token is exhausted while others keep paging; no rows are lost,\nbut merge pages by `token_id`, not by array position.","operationId":"get_holders","parameters":[{"name":"condition","in":"query","description":"Comma-separated `condition_id`s (at most 20 distinct values; exactly\none with `include_pnl=true`). Required. `condition` is the unified key\nacross v2 (same as the feeds and `/v2/oi`); `condition_id` /\n`conditionId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"Rows per outcome token; defaults to 100, maximum 1000 (100 with\n`include_pnl=true`).","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`; carries\nthe per-token `(limit, offset)` window and overrides `limit`. Paging\npast the first page is cursor-only.","required":false,"schema":{"type":["string","null"]}},{"name":"min_balance","in":"query","description":"Minimum net balance in shares (default 0), applied post-netting. With\n`include_pnl=true` it applies to the served per-side gross amount\ninstead.","required":false,"schema":{"type":["number","null"],"format":"double"}},{"name":"include_pnl","in":"query","description":"Opt into per-holder position economics (default `false`; `includePnl`\nis an accepted alias). Adds `avg_price`, `entry_cost_usdc`,\n`current_price`, `current_value`, `realized_pnl`, `unrealized_pnl` and\n`total_pnl` to every holder row, and switches the served amounts to\nper-side gross balances: a wallet holding both outcomes appears under\nboth tokens with per-side sizes and that side's economics, matching\n`/v2/positions` for the same wallet and token. This mode serves one\nmarket's table at a time: exactly one `condition`, `limit` at most 100.","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"A page of top holders per outcome token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HoldersPage"}}}},"400":{"description":"Missing 'condition', invalid params, or invalid cursor, or a malformed 'condition' id; with 'include_pnl', also more than one 'condition' or a limit above 100 (including a cursor that carries a wider window)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/leaderboard":{"get":{"tags":["boards"],"summary":"Get the trader leaderboard","description":"The ranked board of realized PnL, combos included.\n\n`?time_period=` is `day` (default), `week`, `month` or `all`; `?category=`\nis `overall` (default) or a market category; `?sort_by=` picks the `PNL`\n(default) or `VOLUME` board. Deeper pages come only from `?cursor=`.\n\nA cursor **pins the board it was minted on**; sort, window and category;\nso following it needs no params at all, and restating a different one is a\n`400` rather than a silent re-point (the builders-board pattern).\n\n`?user=` answers a different question; one wallet's standing, carrying\n**both** the PnL and volume ranks in a single object rather than a page. A\nrank of `0` there means unranked for that board, not first. `sort_by`,\n`limit` and `cursor` do not apply to that arm.\n\n**`rank` ties and skips**: tied users share a rank and the next one jumps,\nso a partition's highest rank approaches its row count. Page with the\ncursor; never compute a page from a rank.\n\nFinite windows (day/week/month) serve the MARKED equity change net of\nflows; they move with unrealized marks; `all` is the realized-only\nlifetime ledger. `volume` is in shares, not USDC.","operationId":"get_leaderboard","parameters":[{"name":"time_period","in":"query","description":"Window: `day` | `week` | `month` | `all`. Defaults to `day`.","required":false,"schema":{"type":["string","null"]}},{"name":"category","in":"query","description":"`overall` (default), a Gamma market category (e.g. `sports`), or a\nsynthetic category: `combos` (combinatorial positions; PNL boards only;\nthe volume board has no combos rows) or `esports` (promoted subcategory).","required":false,"schema":{"type":["string","null"]}},{"name":"sort_by","in":"query","description":"Which board: `PNL` (default) or `VOLUME`.","required":false,"schema":{"type":["string","null"]}},{"name":"user","in":"query","description":"Look up one wallet's standing instead of reading the board. Returns a\nsingle object carrying both ranks, not a page.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied.","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of the board, or one wallet's standing when `user` is given","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}},"400":{"description":"Board arm: invalid `time_period`, `sort_by`, or `cursor`, including a param that contradicts the cursor's pinned board. User arm (`?user=`): invalid `time_period` only; `sort_by`, `limit` and `cursor` do not apply there and are ignored, not rejected, but a `user` that is a known protocol contract address is refused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/live-volume":{"get":{"tags":["markets"],"summary":"Get live volume for an event","description":"Cumulative one-side (taker) volume per market.\n\nPass `?event_id=` as a comma-separated list of integer event ids (aliases `id` / `eventId`); every market under those events is returned, `taker_volume`\ndescending, with `taker_volume_total` their sum. A list spans events. Unlike the\nfeeds this is not paginated; `data` is\nthe object with no `pagination`.\n\nUnparseable ids are ignored; a request whose ids are *all* unparseable is a\n400 rather than an empty 200, so a typo cannot read as \"no volume\". Ids are\nsorted and deduplicated before the lookup, so `?event_id=20,10` and\n`?event_id=10,20` are the same request and share a cache entry.","operationId":"get_live_volume","parameters":[{"name":"event_id","in":"query","description":"Event id(s), comma-separated. Required. `event_id` is the unified key\nacross v2 (same as the feeds); `id` and `eventId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Per-market taker volume for the requested event(s), plus taker_volume_total","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_LiveVolume"}}}},"400":{"description":"Missing or unparseable event_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/oi":{"get":{"tags":["markets"],"summary":"Get open interest","description":"Priced gross open interest per market.\n\nPass `?condition=` as a comma-separated list of condition ids (aliases `condition_id` / `conditionId`, matching the feeds); omit it for the single\nglobal figure (`condition_id = \"GLOBAL\"`, still a one-element array).\nEvery requested id that resolves to a servable market (indexed, active,\nnot archived; any id family) returns a row, with `value: 0` when\nnothing is held; an id absent from `data` did not resolve to a servable\nmarket. A malformed id is a `400` naming the value, so absence carries that\none meaning and nothing else. Unlike the feeds this is not paginated;\n`data` is the row array with no `pagination`.","operationId":"get_oi","parameters":[{"name":"condition","in":"query","description":"Condition id(s), comma-separated (at most 20 distinct values).\n`condition` is the unified key across v2 (same as the feeds);\n`condition_id` / `conditionId` are accepted aliases. Omit for global\nopen interest.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Open interest per requested market, or the global figure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_Vec_OpenInterest"}}}},"400":{"description":"Invalid query params, or a malformed 'condition' id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/positions":{"get":{"tags":["wallet"],"summary":"List positions for a user or market","description":"A keyset page of positions in the standard\n`{ data, pagination }` envelope. One route serves a user's open book, their\nclosed book (`status=CLOSED`), and a market's holders (market anchor).\n\nAt least one of `user`/`condition` is required. Supplying both anchors on the\nuser and applies `condition` as a narrowing filter.\n\n`status` defaults to `OPEN`, which is the **superset**: a\nsettled-but-unredeemed winner still holds its tokens, so it is an open\nposition whose condition resolved. `REDEEMABLE` narrows to that subset, and\neach row echoes its own `status`.\n\nResume contract: a `next_cursor` binds the `status`/`sortBy`/`sortDirection`\nthe walk started with, and following it needs nothing but `?cursor=`; the\ntoken is the authority on the spine and the total order, and the handler\nadopts all three from it. Restating them is allowed and must agree;\n**explicitly** contradicting one is a 400, because replaying an anchor under\na different spine or order would silently walk a different result set.\nOmitting them is not a contradiction; a defaulted `status` is the absence of\na choice, not a request for `OPEN`.\n\nA malformed `condition` id is a `400` naming the value; a\nwell-formed one that matches nothing serves an empty `data` array, which\nis the meaningful zero-state; absence means the market is not servable,\nand only that.","operationId":"get_positions","parameters":[{"name":"user","in":"query","description":"The wallet to anchor on. At least one of `user`/`condition` is required.","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Condition id(s), comma-separated (at most 20 distinct values). With\n`user`, narrows that user's positions (all ids honoured). Without\n`user`, anchors on the market's holders; exactly one id is accepted\nthere, and a multi-id list is rejected rather than silently truncated.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied (the cursor's size wins).","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`. It\ncarries the page position, page size, and the status/sort/direction it\nwas minted under.","required":false,"schema":{"type":["string","null"]}},{"name":"status","in":"query","description":"One of `OPEN`, `REDEEMABLE`, or `CLOSED`; defaults to `OPEN`.\n\n`OPEN` is the superset; it includes settled-but-unredeemed winners,\nwhich `REDEEMABLE` narrows to. `CLOSED` is exited positions.","required":false,"schema":{"type":["string","null"]}},{"name":"event_id","in":"query","description":"Event id(s), comma-separated. User-anchored only.","required":false,"schema":{"type":["string","null"]}},{"name":"title","in":"query","description":"Case-insensitive market-title substring filter, honoured on every\nanchor and status. SQL LIKE wildcards (`%`, `_`) keep their usual\nmeaning; empty or whitespace-only is treated as absent; at most 200\ncharacters. NOT carried by the cursor: re-send it on every page of a\nwalk (like `condition` and the `start`/`end` window), or the cohort\nsilently widens.","required":false,"schema":{"type":["string","null"]}},{"name":"filter_type","in":"query","description":"`CASH` or `TOKENS`; defaults to `TOKENS` (the /v2/trades-homogenized\nfilter pair, replacing the former `size_threshold`).","required":false,"schema":{"type":["string","null"]}},{"name":"filter_amount","in":"query","description":"The filter floor. `TOKENS`: minimum CURRENT holding in shares\n(defaults to the 0.1 dust floor; applies to `OPEN`/`REDEEMABLE`; a\nuser's `CLOSED` set is not narrowed by it, and on a market anchor it\nmoves the OPEN/CLOSED boundary). `CASH`: minimum mark-to-market\n`current_value` in USDC, on top of the token dust floor. Invalid\nvalues fall back to the default.","required":false,"schema":{"type":["number","null"],"format":"double"}},{"name":"include_archived","in":"query","description":"Also include positions on archived markets; defaults to `false`.\n`OPEN`/`REDEEMABLE` only; combining it with `status=CLOSED` is\nrejected. Inactive markets remain excluded either way.","required":false,"schema":{"type":["boolean","null"]}},{"name":"sort_by","in":"query","description":"One of `CURRENT_VALUE`, `TOKENS`, `UNREALIZED_PNL`, `REALIZED_PNL`,\n`TOTAL_PNL`, or `TIMESTAMP` (the row's `last_event_at`). The default\nfollows the status: `CURRENT_VALUE` for `OPEN`/`REDEEMABLE`,\n`REALIZED_PNL` for `CLOSED`.","required":false,"schema":{"type":["string","null"]}},{"name":"start","in":"query","description":"Inclusive lower bound on `last_event_at`, epoch seconds; omit or `0` for\nunbounded (the `/v2/activity` + `/v2/trades` vocabulary).","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"end","in":"query","description":"Inclusive upper bound on `last_event_at`, epoch seconds; omit or `0` for\nunbounded.\n\nA position with no native economics carries no `last_event_at` and is\ntherefore **excluded by any bound**, in either direction; a window asks\nwhich positions moved inside it, and a row with no clock has no answer.\nUnbounded requests still serve those rows.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"sort_direction","in":"query","description":"`ASC` or `DESC`; defaults to `DESC`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of positions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsPage"}}}},"400":{"description":"Missing anchor, invalid query params or cursor, an unknown status/sort/direction, a malformed 'condition' id, an over-long 'title', or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/positions/combos":{"get":{"tags":["wallet"],"summary":"List combo positions","description":"Combo positions for a user, in the standard\n`{ data, pagination }` envelope.\n\nSorts: `FIRST_ENTRY` (default) | `ENTRY_COST` (+ `CURRENT_VALUE` alias) |\n`UPDATED`, each with `sort_direction`. `FIRST_ENTRY DESC` pages by the\ntwo-state keyset anchor `(first_entry_at_micros, combo_condition_id,\noutcome_index)` (NULL micros = the NULL tail); `UPDATED ASC` by the\nsingle-state `(updated_at_micros, …)` anchor; every other combination by an\noffset-shaped token. The cursor binds sort + direction and the resume\nADOPTS them, so a replay cannot flip or re-sort the walk mid-stream.\n\nIt binds the cohort; `user`/`status`/`condition`/`updated_after`/\n`updated_before`; the same way: following a\npage needs nothing but `?user=` (always required here) and `?cursor=`, and\nrestating a filter is allowed but must agree. Omitting one is not a\ncontradiction, it is the absence of a choice; **contradicting** one is a\n400, because the token's walk state only means anything against the cohort\nit was minted on.\n\nIncremental sync: `updated_after`/`updated_before` are an INCLUSIVE\nepoch-second window on `updated_at`. Without a `status` filter, either\nbound switches the response to the mirror-complete sync view (every live\nrow, not only held ones); a `status` filter keeps its own visibility. The\nupper end is always capped by a short stability ceiling (~90s behind now)\nso a mirror never reads rows that may still move. Pair with\n`sortBy=UPDATED&sortDirection=ASC` for the stable sync order.\n\nA malformed `condition` combo condition id is a `400` naming the value; a\nwell-formed one that matches nothing serves an empty `data` array, which\nis the meaningful zero-state.","operationId":"get_combo_positions","parameters":[{"name":"user","in":"query","description":"The wallet to anchor on. Required; combo positions are user-anchored.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied (the cursor's size wins).","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Combo condition id(s), comma-separated (at most 20 distinct values).\n`condition_id` / `conditionId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}},{"name":"status","in":"query","description":"One of `OPEN`, `REDEEMABLE`, `PARTIAL`, `RESOLVED_WIN`, `RESOLVED_LOSS`,\n`RESOLVED_PARTIAL`; default (absent) is the held-visibility listing.\n\nAligned with `/v2/positions`: `OPEN` is the superset; it includes\nstill-held redeemable positions; and `REDEEMABLE` narrows to exactly\nthe rows whose `redeemable` flag is `true`. `REDEEMABLE` must be the\nsole value; the other values may be combined comma-separated and keep\nper-value equality semantics.","required":false,"schema":{"type":["string","null"]}},{"name":"sort_by","in":"query","description":"`FIRST_ENTRY` (default, except under `status=REDEEMABLE`, which defaults\nto `ENTRY_COST` so the largest claims lead) | `ENTRY_COST` |\n`CURRENT_VALUE` (alias of `ENTRY_COST`) | `UPDATED`. `FIRST_ENTRY DESC`\nand `UPDATED ASC` page by keyset; every other combination pages by an\noffset-shaped cursor. The minted cursor binds sort + direction along\nwith the `status`/`condition` cohort, so a page-2 request needs only\n`?user=` and `?cursor=`; restating a filter is allowed but must agree.","required":false,"schema":{"type":["string","null"]}},{"name":"sort_direction","in":"query","description":"`ASC` or `DESC` (default `DESC`).","required":false,"schema":{"type":["string","null"]}},{"name":"updated_after","in":"query","description":"Incremental-sync watermark: INCLUSIVE lower bound on `updated_at`,\nepoch seconds. Without a `status` filter, either watermark serves the\nsync view; every live row (mirror-complete), not only the held\nlisting; a `status` filter keeps its own row visibility. The window's\nupper end is always capped by a short stability ceiling (about 90\nseconds behind now), so a bound in the future cannot serve rows that\nmay still move.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"updated_before","in":"query","description":"Incremental-sync watermark: INCLUSIVE upper bound on `updated_at`,\nepoch seconds; must not precede `updated_after`. See `updated_after`\nfor the sync-view and ceiling semantics.","required":false,"schema":{"type":["integer","null"],"format":"int64"}}],"responses":{"200":{"description":"A page of combo positions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboPositionsPage"}}}},"400":{"description":"Invalid query params or cursor, an invalid sync watermark (negative, or an inverted window), a malformed 'condition' combo id, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/prices-history":{"get":{"tags":["markets"],"summary":"Get a token's price history","description":"The price-history series for one outcome token, or\na single point-in-time observation.\n\nThree window forms, exactly one per request: `start` (with optional `end`),\n`interval`, or `as_of`. Points are served oldest-first; pass `?cursor=` from\na prior response's `next_cursor` for the next page.\n\n`interval=max` (or `all`) serves the market's whole life, back to 2022 for\nthe oldest markets, at 12-hour buckets unless `bucket_seconds` says\notherwise; explicit `start`/`end` windows cap at 15 days, so the presets\nare the long-range path.\n\nThe series ends with a **terminal point**: the latest observation inside the\nwindow, which is a real tick and so can fall between bucket boundaries.\nNothing may assume uniform spacing (sparse data already forbids that), and\neach point's `resolution_seconds` says what window it was observed in.\n\n**Resolution has a shelf life, so a window's AGE decides what it can be\nserved at.** 1-minute data is kept 7 days, 5-minute 60 days, 30-minute 90\ndays; the 3-hour and 12-hour series are permanent (back to 2022-11-18). So\n`bucket_seconds=60` over a window starting a month ago is an incompatible\npair: both values are valid, and there is no data at their intersection.\n\nThe two ways of asking behave differently on purpose:\n\n* **`bucket_seconds` sent** is served exactly as asked, so over a window\n  whose resolution has expired you get an empty page rather than a silent\n  substitution.\n* **`bucket_seconds` omitted** lets the server choose a width that can\n  actually serve the window: the finest tier grain whose series stays under\n  ~2,500 points, coarsened further if that grain does not reach the window's\n  start. A window up to a day keeps 1-minute detail (an hour 60 points, a day\n  1,440); beyond that it moves to a materialized tier (three days 864, a week\n  2,016, fifteen days 720, a month 1,440). Send `bucket_seconds` when you\n  want a specific density instead.\n\n`resolution_seconds` on every point reports what it was served at, so read it\ninstead of assuming the width a recent window would have given you. For a\nmulti-day window prefer a grain-aligned `bucket_seconds` (300, 1800, 10800,\n43200) or omit it; a 60-second width over days is the one shape that is both\nslow and, past 7 days, empty.","operationId":"get_prices_history","parameters":[{"name":"token_id","in":"query","description":"Outcome token id (the CLOB asset id the chart is keyed by). Required.\n`tokenId` is an accepted alias.","required":false,"schema":{"type":["string","null"]}},{"name":"start","in":"query","description":"Window start, epoch seconds, INCLUSIVE. Alone it means \"up to the\npresent\", and is capped at 15 days back from now.\n\nPass `end` too when paging: a window that tracks the present keeps\ngrowing at the tip, and the 15-day cap is re-checked on every page, so a\nwalk that starts near the cap can outlive it.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"end","in":"query","description":"Window end, epoch seconds, EXCLUSIVE. Requires `start`; on its own it\nwould ask for every point ever recorded up to `end`.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"interval","in":"query","description":"Relative window INSTEAD of `start`/`end`: `max`, `all`, `1m`, `1w`,\n`1d`, `6h`, `1h`, matched case-sensitively. An empty `interval=` is a\nmalformed value, not an absent one.\n\n`max`/`all` serve the market's WHOLE life (back to 2022 for the oldest\nmarkets) at 12-hour buckets by default; at `bucket_seconds` of 10800 or\n43200 the window is unbounded, while finer widths keep a 30-day window.\nThe other intervals take a width sized to their own span when\n`bucket_seconds` is omitted (`1h`/`6h`/`1d` 60, `1w` 300, `1m` 1800), and\neach still floors an explicit value: 600 for `max`/`all`/`1m`, 300 for\n`1w`.","required":false,"schema":{"type":["string","null"]}},{"name":"bucket_seconds","in":"query","description":"Bucket width in SECONDS (60…86400). `bucketSeconds` is an accepted alias.\n\nOMIT it and the server sizes the width to the window: the finest tier\ngrain (60, 300, 1800, 10800, 43200) that keeps the series under ~2,500\npoints, coarsened further if that grain no longer reaches the window's\nstart. So a window up to a day keeps 1-minute detail, three days and a\nweek default to 300, fifteen days and a month to 1800, and an unbounded\n`max`/`all` to 43200.\n\nSEND it and it is served exactly as asked, which for a window older than\nthat resolution's retention means an empty page rather than a silent\nsubstitution. An explicit value is also floored per interval: 600 for\n`max`/`all`/`1m`, 300 for `1w`.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"as_of","in":"query","description":"Point-in-time read, epoch seconds, INCLUSIVE: the latest observation at\nor before this instant. Cannot be combined with a window. `asOf` is an\naccepted alias.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"limit","in":"query","description":"First-page size; defaults to the cap (10,000). Ignored when `cursor` is\nsupplied (the cursor's size wins).","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":10000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of the price-history series","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricesHistoryPage"}}}},"400":{"description":"Invalid query params or cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Timescale pool saturated; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/resolutions":{"get":{"tags":["markets"],"summary":"Get resolution state","description":"Complete resolution state by one selector family.\n\nSupply exactly one of `question_id`, `condition`, or `event_id`. Condition and\nevent selectors accept comma-separated values and return condition-grain\nrows in deterministic order, preferring native V2 lifecycle, then UMA\nlifecycle, then terminal CTF state. Misses return `{ \"data\": [] }`.","operationId":"get_resolutions","parameters":[{"name":"question_id","in":"query","description":"One UMA question identifier (`0x` plus 64 hexadecimal characters).","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Comma-separated Gamma condition identifiers (at most 20 distinct values).","required":false,"schema":{"type":["string","null"]}},{"name":"event_id","in":"query","description":"Comma-separated positive Gamma event IDs (at most 20 distinct values).","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Resolution rows for the selected question, markets, or events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_Vec_Resolution"}}}},"400":{"description":"Missing, mixed, empty, or invalid selector","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/status":{"get":{"tags":["service"],"summary":"Get data freshness","description":"How fresh the data behind this API is.\n\n`/readyz` answers whether this pod can reach its datastore; this answers how\nfar behind chain head what you are reading is. Two halves, because each is\nblind exactly where the other sees:\n\n* `serving`; the projections that turn ingested rows into what the feeds\n  read (`activity_feed` enrichment, `custody_balances` sync, the PnL engine).\n  Each carries its own clock, so this is the only half that can see\n  \"everything stopped\". `lag_seconds` is the worst age across them and\n  `worst` names which one, so a single stalled projection cannot hide behind\n  two healthy ones.\n* `ingestion`; one crawl cursor per `(contract, event)`, summarised as the\n  tail, the furthest-behind block, and the worst few cursors BY NAME. Every\n  reading here is relative or positional, so under a total stall it reads\n  green; that is why `serving` exists alongside it.\n\nStreams that are dormant by design are dropped from `ingestion` rather than\nreported, because they sit arbitrarily far back forever and would otherwise\nfill the list and push the stream you care about off it.\n\nTakes no parameters and is not paginated. Served from a snapshot refreshed\nin the background, never computed on the request: `computed_at` and\n`age_seconds` say how old it is, so a stalled refresher or a datastore\noutage shows up as a growing age rather than a 500. Before the first refresh\nlands there is nothing to serve and this answers `503`; \"not measured yet\"\nand \"measured, no lag\" are different claims.","operationId":"get_status","responses":{"200":{"description":"Serving and ingestion freshness","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_ServiceStatus"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"No freshness has been measured yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/trades":{"get":{"tags":["feeds"],"summary":"List trades","description":"Keyset-paginated trade feed in the standard\n`{ data, pagination }` envelope.\n\nPass `?cursor=` from a prior response's `next_cursor` to fetch the next page;\nit carries both the page size and the `(block_timestamp, sequence_id)` seek\nanchor, so deep pages cost the same as shallow ones.\n\nA malformed `condition` id is a `400` naming the value; a\nwell-formed one that matches nothing serves an empty `data` array, which\nis the meaningful zero-state; absence means the market is not servable,\nand only that.","operationId":"get_trades","parameters":[{"name":"user","in":"query","description":"Address to filter by; omit for the market/event/global feed.","required":false,"schema":{"type":["string","null"]}},{"name":"limit","in":"query","description":"First-page size. Ignored when `cursor` is supplied (the cursor's size wins).","required":false,"schema":{"type":["integer","null"],"format":"int32","maximum":1000,"minimum":0}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from a prior response's `next_cursor`.","required":false,"schema":{"type":["string","null"]}},{"name":"taker_only","in":"query","description":"Defaults to `true`: each fill is served once, on its taker side.\n`false` includes the maker rows too.","required":false,"schema":{"type":["boolean","null"]}},{"name":"filter_type","in":"query","description":"CASH or TOKENS; defaults to TOKENS.","required":false,"schema":{"type":["string","null"]}},{"name":"filter_amount","in":"query","description":"Minimum trade size; defaults to 0.01, and 0 means the same.","required":false,"schema":{"type":["number","null"],"format":"double"}},{"name":"start","in":"query","description":"Window start on `block_timestamp`, epoch seconds (inclusive); honored\non the `user` shape only. Omitted or `0` floors to three years back;\n`start=1` asks for full history. The `condition`/`event_id` shapes\nserve a fixed three-year window and the bare feed the rolling\ncurrent-plus-previous month, ignoring both bounds.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"end","in":"query","description":"Window end, epoch seconds (inclusive); honored on the `user` shape\nonly; omitted or `0` means now plus one day.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"condition","in":"query","description":"Condition id(s), comma-separated (at most 20 distinct values).\n`condition_id` / `conditionId` are accepted aliases.","required":false,"schema":{"type":["string","null"]}},{"name":"event_id","in":"query","description":"Event id(s), comma-separated.","required":false,"schema":{"type":["string","null"]}},{"name":"side","in":"query","description":"BUY or SELL.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"A page of trades","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradesPage"}}}},"400":{"description":"Invalid query params or cursor, a malformed 'condition' id, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/user-pnl":{"get":{"tags":["wallet"],"summary":"Get a user's PnL series","description":"Complete cumulative native-PnL atoms and compositions.","operationId":"get_user_pnl_v2","parameters":[{"name":"user","in":"query","description":"Proxy wallet. The `user_address` spelling is accepted as an alias.","required":false,"schema":{"type":["string","null"]}},{"name":"interval","in":"query","description":"Window: `max`, `all`, `1m`, `1w`, `1d`, `12h`, or `6h`. Defaults to `1d`.","required":false,"schema":{"type":["string","null"]}},{"name":"fidelity","in":"query","description":"Output grid: `1d`, `18h`, `12h`, `3h`, or `1h`. Defaults to `1h`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Cumulative user-PnL series","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_UserPnlSeries"}}}},"400":{"description":"Invalid wallet, interval, or fidelity, including a wallet that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/user-stats":{"get":{"tags":["wallet"],"summary":"Get a user's profile stats","description":"The profile card for one wallet in a single call.\n\n`?user=` is required. Returns `{ data: { trades, biggest_win, views,\njoin_date, all_time_pnl } }`, or `{ data: null }` when the wallet is not a\nknown user.\n\n**`data: null` and a row of zeros mean different things.** `null` is \"no such\nuser\"; zeros are \"this user exists but has never traded, never won and has no\nprofile views\".\n\n`trades` counts DISTINCT MARKETS traded, not individual trades. It is exact,\nnot estimated.\n\n`biggest_win` is the best single **resolved** position win in USDC, market\nand combo arms unified, and `0` when the wallet has no win over $1.\n\n`join_date` is epoch seconds, or `null` when unknown.\n\n`all_time_pnl` is the newest persisted cumulative `/v2/user-pnl` point at\nits actual observation timestamp. It is `null` when the user exists but no\nobservation has been published yet. For the composition card: trading\nrealized is `realized_market_pnl + realized_combo_pnl`; LP realized is\n`realized_lp_pnl`; rebates, yield, rewards, referral, and fees paid map to\ntheir same-named fields (`fees_paid` is refunds minus charges). `volume`,\n`volume_usdc`, and `trade_count` are cumulative maker-attributed canonical\nfill metrics.\n\nNot paginated: one row by construction, so `data` is the bare object with no\n`pagination`; the `/v2/value` shape.","operationId":"get_user_stats","parameters":[{"name":"user","in":"query","description":"The wallet whose profile stats to return. Required; `0x` followed by\n40 hexadecimal characters.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"The wallet's profile stats, or null when it is not a known user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_Option_UserStats"}}}},"400":{"description":"Missing or invalid 'user' address, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/user-volume":{"get":{"tags":["wallet"],"summary":"Get a user's trading volume","description":"One wallet's trading volume over a window, in both\nunits side by side.\n\n`?user=` is required. `?start=` / `?end=` are epoch seconds, inclusive and\noptional: omitted or `0` disables a bound (full history). Volume is tracked in\nwhole UTC days, so each bound is floored to its UTC day; the served window\nis the smallest whole-day window containing `[start, end]`.\n\nReturns `{ data: { volume, volume_usdc, trade_count } }`; exactly one row\nby construction (the view aggregates with no GROUP BY), zeros for a wallet\nwith no trades in the window. An inverted window is zeros too, not an error.\n\n`volume` is both-sides SHARES; `volume_usdc` is the same measure in USD;\nthe endpoint that shows the unit convention side by side: the bare name is\nthe natural unit, `_usdc` is the denomination, the same pairing as\n`current_size` / `entry_cost_usdc` on `/v2/positions`.","operationId":"get_user_volume","parameters":[{"name":"user","in":"query","description":"The wallet whose volume to return. Required.","required":false,"schema":{"type":["string","null"]}},{"name":"start","in":"query","description":"Window start, epoch seconds, inclusive. Omitted or `0` disables the\nbound (the feeds' convention). Volume is tracked in whole UTC days, so\nthe bound is floored to its UTC day.","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"end","in":"query","description":"Window end, epoch seconds, inclusive, floored to its UTC day. Omitted\nor `0` disables the bound.","required":false,"schema":{"type":["integer","null"],"format":"int64"}}],"responses":{"200":{"description":"The wallet's volume over the window: both-sides shares, the same measure in USD, and the trade count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_UserVolume"}}}},"400":{"description":"Missing or empty 'user', or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too many requests; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/value":{"get":{"tags":["wallet"],"summary":"Get portfolio value","description":"The user's portfolio value: single-market holdings marked to market plus\nunresolved combo positions at cost basis.\n\n`?user=` is required (400 otherwise). `?condition=` (CSV of `condition_id`)\nscopes the single-market term, and any condition filter excludes the\nportfolio-level combo term. `data` is a single object; a user\nwith no positions yields `{ \"data\": { \"proxy_wallet\": …, \"value\": 0 } }`.","operationId":"get_value","parameters":[{"name":"user","in":"query","description":"The wallet whose portfolio value to return. Required.","required":false,"schema":{"type":["string","null"]}},{"name":"condition","in":"query","description":"Comma-separated `condition_id`s (at most 20 distinct values); omit for\nthe full portfolio.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Portfolio value for the user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Envelope_PortfolioValue"}}}},"400":{"description":"Missing or empty 'user', a malformed 'condition' id, or a 'user' that is a known protocol contract address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Service is at heavy-query capacity; retry after `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"Activity":{"type":"object","description":"One activity-feed event (`/v2/activity`); a trade, split, merge, redeem, …","required":["proxy_wallet","timestamp","condition_id","type","size","usdc_size","transaction_hash","price","token_id","side","outcome_index","title","slug","icon","event_slug","outcome","name","pseudonym","bio","profile_image","profile_image_optimized"],"properties":{"bio":{"type":"string","description":"Profile bio text."},"condition_id":{"type":"string","description":"On-chain condition id of the market (`0x` hex)."},"event_slug":{"type":"string","description":"Parent event slug."},"icon":{"type":"string","description":"Market icon URL."},"is_combo":{"type":"boolean","description":"Flag only, on V2/V3 combo trade rows. Combo detail lives on the combos\nendpoints; omitted from non-combo rows."},"name":{"type":"string","description":"Profile display name of the wallet."},"outcome":{"type":"string","description":"Label of the outcome (e.g. `Yes`)."},"outcome_index":{"type":"integer","format":"int32","description":"Index of the outcome within the market; `999` means the outcome\ncould not be labeled."},"price":{"type":"number","format":"double","description":"Price per share in USDC (trades; `0` where no price applies)."},"profile_image":{"type":"string","description":"Profile image URL."},"profile_image_optimized":{"type":"string","description":"Resized profile image URL, when one exists."},"proxy_wallet":{"type":"string","description":"Proxy wallet the row belongs to; the address every wallet-keyed\nendpoint accepts as `user`."},"pseudonym":{"type":"string","description":"Generated fallback handle for profiles without a display name."},"side":{"type":"string","description":"`BUY` or `SELL` on trade rows, from this wallet's perspective; empty\nwhere a side does not apply."},"size":{"type":"number","format":"double","description":"Share quantity of the action; bare sizes are shares, never USD."},"slug":{"type":"string","description":"Market slug; the URL segment on polymarket.com."},"timestamp":{"type":"integer","format":"int64","description":"Block timestamp of the action, epoch seconds."},"title":{"type":"string","description":"Market question title (Gamma enrichment; empty when unenriched)."},"token_id":{"type":"string","description":"CLOB asset id of the outcome token the action touched."},"transaction_hash":{"type":"string","description":"Hash of the settling transaction."},"type":{"type":"string","description":"TRADE, SPLIT, MERGE, REDEEM, REWARD, CONVERSION, …"},"usdc_size":{"type":"number","format":"double","description":"Cash value of the action in USDC."}}},"ActivityPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/activity`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Activity"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"ApprovalContract":{"type":"object","description":"One trusted approval contract in the public response.","required":["id","feature","token","spender","standard","approved"],"properties":{"amount":{"type":["string","null"],"description":"Current ERC20 allowance: `max` for an unlimited grant, else the raw\ninteger amount as a string; absent on ERC1155 operator approvals\n(all-or-nothing)."},"approved":{"type":"boolean","description":"Whether the wallet currently grants this approval."},"feature":{"type":"string","description":"The product flow the approval enables (e.g. `trading`)."},"id":{"type":"string","description":"Catalog identifier of this approval pair (token + spender)."},"spender":{"type":"string","description":"The contract approved to spend or operate the token."},"standard":{"type":"string","description":"Token standard of the pair: `ERC20` or `ERC1155`."},"token":{"type":"string","description":"The token contract the approval is granted on."}}},"Approvals":{"type":"object","description":"Non-paginated approval snapshot for one Polygon proxy wallet.","required":["address","chain_id","checked_at","contracts"],"properties":{"address":{"type":"string","description":"The checked wallet."},"chain_id":{"type":"integer","format":"int32","description":"EVM chain id the state was read on (137 = Polygon)."},"checked_at":{"type":"string","description":"When the on-chain state was read, RFC3339 UTC (20-second server cache)."},"contracts":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalContract"},"description":"One row per catalog pair the wallet may need."}}},"BiggestWinner":{"type":"object","description":"One `/v2/biggest-winners` row: a single winning POSITION, not a user total.\n\n`kind` is `market` or `combo`. Combo rows carry a `' / '`-joined title of\ntheir legs and have no Gamma event; `event_id` is `0` and `event_slug` is\nempty; so branch on `kind` before building an event link.","required":["win_rank","kind","user_id","pnl","initial_value","final_value","resolved_at","condition_id","position_id","event_id","event_slug","event_title","user_name","profile_image"],"properties":{"condition_id":{"type":"string","description":"On-chain condition id of the market (combo rows: the combo condition)."},"event_id":{"type":"integer","format":"int32","description":"Gamma event id of the parent event; `0` on combo rows."},"event_slug":{"type":"string","description":"Parent event slug; empty on combo rows."},"event_title":{"type":"string","description":"Parent event title; on combo rows, the `' / '`-joined leg questions."},"final_value":{"type":"number","format":"double","description":"Value at resolution, in USDC."},"initial_value":{"type":"number","format":"double","description":"Cost basis of the winning position, in USDC."},"kind":{"type":"string","description":"`market` or `combo`; combo rows carry no Gamma event (`event_id` 0,\nempty `event_slug`), so branch on this before building event links."},"pnl":{"type":"number","format":"double","description":"`final_value - initial_value`, in USDC."},"position_id":{"type":"string","description":"Token id of the winning position."},"profile_image":{"type":"string","description":"Profile image URL."},"resolved_at":{"type":"integer","format":"int64","description":"Unix seconds; when the position resolved."},"user_id":{"type":"string","description":"The winning wallet."},"user_name":{"type":"string","description":"Profile display name of the wallet."},"win_rank":{"type":"integer","format":"int32","description":"Unique 1-based ordinal within the window/category; `row_number()`, so\nequal PnL does not share a rank (unlike the leaderboard's `rank`).","minimum":0}}},"BiggestWinnersPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/biggest-winners`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BiggestWinner"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"BuilderStanding":{"type":"object","description":"One `/v2/builders/leaderboard` row: a builder's standing for the window.\n\n`volume` is in SHARES, not USDC; the same unit as `/v2/leaderboard`'s `volume`.\n`active_users` counts distinct makers in the window. `builder_name` is a\ndisplay name that falls back to `builder_code` when the builder has no\nprofile; `profile_image` is the avatar, the same spelling every payload\ncarrying one uses.","required":["rank","builder_name","builder_code","profile_image","verified","volume","active_users"],"properties":{"active_users":{"type":"integer","format":"int64","description":"Distinct active users attributed to the builder in the window.","minimum":0},"builder_code":{"type":"string","description":"Stable identifier of the builder."},"builder_name":{"type":"string","description":"Builder display name; cosmetic; key on `builder_code`."},"profile_image":{"type":"string","description":"Builder profile image URL."},"rank":{"type":"integer","format":"int64","description":"Board rank in the requested window; ties share a rank and the next skips.","minimum":0},"verified":{"type":"boolean","description":"Whether the builder is verified."},"volume":{"type":"number","format":"double","description":"Volume attributed to the builder in the window, in shares."}}},"BuilderVolumePoint":{"type":"object","description":"One `/v2/builders/volume` row: a builder's volume in ONE bucket of the\nseries, not a running total.\n\n`date` is the bucket start (`YYYY-MM-DD`) and its width is the request's\n`interval`; daily, weekly, monthly, or yearly for `all`. `rank` is the\nbuilder's placing **within that bucket**, so it moves from bucket to bucket.\n`volume` is in SHARES, as on the leaderboard.","required":["date","rank","builder_name","builder_code","profile_image","verified","volume","active_users"],"properties":{"active_users":{"type":"integer","format":"int64","description":"Distinct active users attributed in that bucket.","minimum":0},"builder_code":{"type":"string","description":"Stable identifier of the builder."},"builder_name":{"type":"string","description":"Builder display name; cosmetic; key on `builder_code`."},"date":{"type":"string","description":"Bucket start date, `YYYY-MM-DD` (UTC); `interval` sets the width."},"profile_image":{"type":"string","description":"Builder profile image URL."},"rank":{"type":"integer","format":"int64","description":"Builder's rank within that bucket.","minimum":0},"verified":{"type":"boolean","description":"Whether the builder is verified."},"volume":{"type":"number","format":"double","description":"Volume attributed in that bucket, in shares."}}},"BuildersLeaderboardPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/builders/leaderboard`; an\noffset-cursor board, like `LeaderboardPage`. Its companion\n`/v2/builders/volume` is a series rather than a board and is NOT paged.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BuilderStanding"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"ComboActivity":{"type":"object","description":"One combo lifecycle/redemption event (`/v2/activity/combos`).\n\nOrdered and paginated by on-chain position; `(block_number, log_index)`.\n`timestamp` is the event's wall-clock, not the ordering key.","required":["id","type","proxy_wallet","combo_condition_id","combo_position_id","block_number","timestamp","transaction_hash","legs"],"properties":{"amount_usdc":{"type":["number","null"],"format":"double","description":"Cash amount of the action in USDC; `null` where no cash leg applies."},"block_number":{"type":"integer","format":"int64","description":"Block number of the action."},"combo_condition_id":{"type":"string","description":"On-chain combo condition id (structural, `0x03`-prefixed)."},"combo_position_id":{"type":"string","description":"Token id of the combo position the action touched."},"id":{"type":"string","description":"`tx_hash-log_index`."},"legs":{"type":"array","items":{"$ref":"#/components/schemas/ComboLeg"},"description":"The combo's legs, in leg order, with market and event enrichment."},"payout_usdc":{"type":["number","null"],"format":"double","description":"Redemption payout in USDC on REDEEM rows; `null` otherwise."},"proxy_wallet":{"type":"string","description":"Proxy wallet the action belongs to."},"timestamp":{"type":"integer","format":"int64","description":"Event time (epoch seconds)."},"transaction_hash":{"type":"string","description":"Hash of the settling transaction."},"type":{"type":"string","description":"Canonical action verb; SPLIT / MERGE / CONVERT / COMPRESS / WRAP /\nUNWRAP / REDEEM. The only action field on the wire; `timestamp` is the\nserved event clock."}}},"ComboActivityPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/activity/combos`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ComboActivity"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"ComboLeg":{"type":"object","description":"One leg of a combo, with its market and event enrichment.","required":["leg_index","leg_position_id","leg_condition_id","leg_outcome_index","leg_outcome_label","leg_status","leg_current_price","market"],"properties":{"leg_condition_id":{"type":"string","description":"On-chain condition id of the leg's market."},"leg_current_price":{"type":"number","format":"double","description":"Live price of the leg outcome (Gamma marks)."},"leg_index":{"type":"integer","format":"int32","description":"Position of the leg within the combo, 0-based."},"leg_outcome_index":{"type":"integer","format":"int32","description":"Index of the outcome the combo takes on this leg; `999` means the\noutcome could not be labeled."},"leg_outcome_label":{"type":"string","description":"Label of the outcome the combo takes on this leg."},"leg_position_id":{"type":"string","description":"Outcome token id of the leg."},"leg_resolved_at":{"type":["string","null"],"description":"Gamma `closed_time`, RFC3339; `null` while open."},"leg_status":{"type":"string","description":"OPEN / RESOLVED_WIN / RESOLVED_LOSS (live resolution state)."},"market":{"$ref":"#/components/schemas/ComboLegMarket","description":"The leg's market, with its (single) event nested."}}},"ComboLegEvent":{"type":"object","description":"A leg market's event.","required":["event_id","event_slug","event_title","event_image"],"properties":{"event_id":{"type":"string","description":"Gamma event id."},"event_image":{"type":"string","description":"Event image URL."},"event_slug":{"type":"string","description":"Event slug; the URL segment on polymarket.com."},"event_title":{"type":"string","description":"Event title."}}},"ComboLegMarket":{"type":"object","description":"A leg's market, with its (single) event nested.","required":["market_id","slug","title","outcome","image_url","icon_url","category","subcategory","tags","end_date","event"],"properties":{"category":{"type":"string","description":"Gamma market category (e.g. `sports`)."},"end_date":{"type":"string","description":"Market end date, RFC3339; empty when Gamma has none."},"event":{"$ref":"#/components/schemas/ComboLegEvent","description":"The market's parent event."},"group_item_title":{"type":"string","description":"Raw short per-leg label, without the fallback `title` applies; `\"\"`\nwhen Gamma has none."},"icon_url":{"type":"string","description":"Market icon URL."},"image_url":{"type":"string","description":"Market image URL."},"line":{"type":["number","null"],"format":"double","description":"The sports line the market is quoted on; `null` when it has none."},"market_id":{"type":"string","description":"Gamma's own market id; NOT the on-chain condition id (that is the\nleg's `leg_condition_id`)."},"outcome":{"type":"string","description":"Label of the leg's outcome on this market."},"outcomes":{"type":"array","items":{"type":"string"},"description":"The market's outcome labels, in outcome-index order; `[]` when Gamma\nhas none. Together with `sports_market_type` and `line`, this lets an\nexecuted combo card render both sides of a leg without a Gamma lookup."},"question":{"type":"string","description":"The market's full question. Serves `\"\"` when Gamma has none.\n\nThe five display-metadata fields below default when absent so cached\npayloads written before they existed still deserialize; the query\nalways serves them."},"slug":{"type":"string","description":"Market slug; the URL segment on polymarket.com."},"sports_market_type":{"type":"string","description":"Granular sports market type (for example `totals` or\n`anytime_touchdowns`); `\"\"` for non-sports markets."},"subcategory":{"type":"string","description":"Gamma market subcategory."},"tags":{"type":"array","items":{"type":"string"},"description":"Reserved; always `[]` today."},"title":{"type":"string","description":"Short per-leg label (`group_item_title`), falling back to the question."}}},"ComboPosition":{"type":"object","description":"One combo position (`/v2/positions/combos`); a user's holding in a single\ncombo outcome, with leg rollups and enrichment.\n\nPaginated on `(first_entry_at_micros, combo_condition_id, outcome_index)`;\nfollow the response's `next_cursor` rather than rebuilding that triple.","required":["combo_condition_id","outcome_index","outcome_label","combo_position_id","proxy_wallet","current_size","entry_avg_price_usdc","entry_cost_usdc","gross_entry_cost_usdc","entry_fees_usdc","realized_payout_usdc","status","redeemable","first_entry_at","legs_total","legs_resolved","legs_pending","legs","updated_at","updated_at_micros"],"properties":{"combo_condition_id":{"type":"string","description":"On-chain combo condition id (structural, `0x03`-prefixed)."},"combo_position_id":{"type":"string","description":"Token id of the combo position."},"current_size":{"type":"number","format":"double","description":"Current holding in shares."},"entry_avg_price_usdc":{"type":"number","format":"double","description":"Weighted-average entry price per share, in USDC."},"entry_cost_usdc":{"type":"number","format":"double","description":"Entry cost basis in USDC (rounded weighted-average form)."},"entry_fees_usdc":{"type":"number","format":"double","description":"Attributed BUY-fee portion of `gross_entry_cost_usdc`, 6-decimal grain.\nSELL fees are exit costs and are excluded."},"first_entry_at":{"type":"string","description":"First acquisition time, RFC3339."},"first_entry_at_micros":{"type":["integer","null"],"format":"int64","description":"Epoch-micros of `first_entry_at`; `null`/absent on the NULL tail."},"gross_entry_cost_usdc":{"type":"number","format":"double","description":"Exact fee-inclusive entry basis at 6-decimal grain; formatting to 6 dp\nrecovers the stored value. Do NOT reconstruct it as\n`entry_cost_usdc + entry_fees_usdc`; `entry_cost_usdc` is rounded WAC;\nthe fee-exclusive basis is `gross_entry_cost_usdc − entry_fees_usdc`."},"legs":{"type":"array","items":{"$ref":"#/components/schemas/ComboLeg"},"description":"The combo's legs, in leg order, with market and event enrichment."},"legs_pending":{"type":"integer","format":"int32","description":"Legs still awaiting resolution."},"legs_resolved":{"type":"integer","format":"int32","description":"Legs whose markets have resolved."},"legs_total":{"type":"integer","format":"int32","description":"Number of legs in the combo."},"outcome_index":{"type":"integer","format":"int32","description":"Index of the combo outcome held; `999` means unlabelable."},"outcome_label":{"type":"string","description":"Label of the combo outcome held."},"proxy_wallet":{"type":"string","description":"The holder's wallet. `proxy_wallet` on every /v2 response; `user` is\nthe REQUEST param vocabulary, never a response field (2026-08-19)."},"realized_payout_usdc":{"type":"number","format":"double","description":"Gross redemption payout received so far in USDC; turnover, not\nprofit; net result = payout minus `gross_entry_cost_usdc`."},"redeemable":{"type":"boolean","description":"Whether the combo can be redeemed now."},"resolved_at":{"type":["string","null"],"description":"When the combo fully resolved, RFC3339; `null` while any leg is open."},"status":{"type":"string","description":"Lifecycle state of the position (OPEN, REDEEMABLE, RESOLVED_WIN,\nRESOLVED_LOSS, RESOLVED_PARTIAL)."},"updated_at":{"type":"string","description":"Last event touching the position, RFC3339."},"updated_at_micros":{"type":"integer","format":"int64","description":"Epoch-micros of `updated_at`."}}},"ComboPositionsPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/positions/combos`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ComboPosition"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"ConditionVolume":{"type":"object","description":"One `/v2/live-volume` row: `taker_volume` is the market's cumulative\none-side (taker) volume, truncated to 6 decimal places; qualified because\nthe boards' `volume` is both-sides, and two measures must not share a name.\n","required":["condition_id","taker_volume"],"properties":{"condition_id":{"type":"string","description":"On-chain condition id of the market (`0x` hex)."},"taker_volume":{"type":"number","format":"double","description":"Cumulative one-side (taker) volume in shares, truncated to 6 decimals."}}},"CursorLag":{"type":"object","description":"One ingestion stream's distance from the furthest-along stream.","required":["source","block","behind_max"],"properties":{"behind_max":{"type":"integer","format":"int64","description":"How many blocks this stream trails the furthest-along stream; `0` for\nthe leader."},"block":{"type":"integer","format":"int64","description":"Last block the stream has ingested through."},"source":{"type":"string","description":"The stream this cursor belongs to, as `<contract>_<event>`."}}},"Envelope_Approvals":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"Non-paginated approval snapshot for one Polygon proxy wallet.","required":["address","chain_id","checked_at","contracts"],"properties":{"address":{"type":"string","description":"The checked wallet."},"chain_id":{"type":"integer","format":"int32","description":"EVM chain id the state was read on (137 = Polygon)."},"checked_at":{"type":"string","description":"When the on-chain state was read, RFC3339 UTC (20-second server cache)."},"contracts":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalContract"},"description":"One row per catalog pair the wallet may need."}}}}},"Envelope_LiveVolume":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"`/v2/live-volume`: one entry per market in the requested event(s), ordered\nby `taker_volume` descending, plus `taker_volume_total`; their sum. Events\nthat resolve to no markets serve `{ taker_volume_total: 0.0, conditions: [] }`.","required":["taker_volume_total","conditions"],"properties":{"conditions":{"type":"array","items":{"$ref":"#/components/schemas/ConditionVolume"},"description":"One row per market under the requested event(s), `taker_volume`\ndescending; empty when the events resolve to no markets."},"taker_volume_total":{"type":"number","format":"double","description":"Sum of the rows' `taker_volume`, in shares."}}}}},"Envelope_Option_LeaderboardUserEntry":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"oneOf":[{"type":"null"},{"type":"object","description":"`/v2/leaderboard?user=`; one user's standing, carrying BOTH ranks.\n\nThe ranked board is materialised per sort, so it can only answer \"where does\nthis user place by PnL\" or \"by volume\", one at a time. This shape comes from\nthe by-user pivot instead and answers both at once.\n\nA `null` rank means **unranked** for that sort: the user exists in the pivot\nbut is filtered out of that board.","required":["user_id","pnl","volume","user_name","profile_image","x_username","verified"],"properties":{"pnl":{"type":"number","format":"double","description":"Window PnL in USDC, same semantics as the board rows (finite windows\nmarked, `all` realized-only)."},"profile_image":{"type":"string","description":"Profile image URL."},"rank_pnl":{"type":["integer","null"],"format":"int32","description":"`None` when unranked on the PnL board.","minimum":0},"rank_volume":{"type":["integer","null"],"format":"int32","description":"`None` when unranked on the volume board.","minimum":0},"user_id":{"type":"string","description":"The looked-up wallet."},"user_name":{"type":"string","description":"Profile display name of the wallet."},"verified":{"type":"boolean","description":"Profile verification badge."},"volume":{"type":"number","format":"double","description":"Both-sides traded volume in shares; never USD."},"x_username":{"type":"string","description":"Linked X handle, when one exists."}}}]}}},"Envelope_Option_UserStats":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"oneOf":[{"type":"null"},{"type":"object","description":"The profile card for one wallet, plus its newest persisted all-time PnL\nobservation.\n\n`join_date` is `null` when unknown, which is a real state rather than an\nerror; a meaningful share of accounts have no recorded creation time.\n`biggest_win` is `0` when the wallet has no win over $1. `all_time_pnl` is\n`null` when the user is known but has no observation yet; a missing user is\nrepresented by the outer response `data: null` instead.","required":["proxy_wallet","trades","biggest_win","views"],"properties":{"all_time_pnl":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UserPnlPoint","description":"Newest persisted cumulative all-time PnL point, or `null` when absent."}]},"biggest_win":{"type":"number","format":"double","description":"Largest single resolved win, in USDC."},"join_date":{"type":["integer","null"],"format":"int64","description":"Epoch seconds, or `null` when the join date is unknown."},"proxy_wallet":{"type":"string","description":"The proxy wallet these lifetime statistics describe."},"trades":{"type":"integer","format":"int64","description":"Distinct markets the wallet traded; an exact count.","minimum":0},"views":{"type":"integer","format":"int64","description":"Profile view count.","minimum":0}}}]}}},"Envelope_PortfolioValue":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"`/v2/value`: the user's portfolio value; single-market holdings marked to\nmarket plus unresolved combo positions at cost basis, rounded to 4 decimals. Always\nexactly one row; a user with no positions returns `{ proxy_wallet, value: 0 }`.","required":["proxy_wallet","value"],"properties":{"proxy_wallet":{"type":"string","description":"The wallet the value was computed for."},"value":{"type":"number","format":"double","description":"Portfolio value in USDC, rounded to 4 decimals: holdings marked to\nmarket plus non-terminal combos at cost basis."}}}}},"Envelope_ServiceStatus":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"`/v2/status` payload.\n\nServed from a snapshot refreshed in the background, never computed on the\nrequest. `computed_at`/`age_seconds` make that explicit rather than implicit:\nif the refresher wedges or its datastore goes away, the answer keeps being\nserved with a growing age instead of turning into a 500; the right degraded\nmode for the endpoint you call when something is already wrong.","required":["computed_at","age_seconds","serving","ingestion"],"properties":{"age_seconds":{"type":"integer","format":"int64","description":"How old the snapshot is, in seconds. Normally under the refresh\ninterval; a value that keeps climbing means the refresher is not\ncompleting, and the freshness figures below are that stale ON TOP of\nwhatever lag they report."},"computed_at":{"type":"string","description":"When this snapshot was taken, RFC 3339 in UTC."},"ingestion":{"$ref":"#/components/schemas/IngestionFreshness"},"serving":{"$ref":"#/components/schemas/ServingFreshness"}}}}},"Envelope_UserPnlSeries":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"Complete v2 user-PnL response data.","required":["proxy_wallet","interval","fidelity","source_fidelity","points"],"properties":{"fidelity":{"type":"string","description":"Grid step the points were synthesized on (`1d`, `18h`, `12h`, `3h`, `1h`)."},"interval":{"type":"string","description":"The window served (`max`, `all`, `1m`, `1w`, `1d`, `12h`, `6h`)."},"points":{"type":"array","items":{"$ref":"#/components/schemas/UserPnlPoint"},"description":"Dense cumulative points on the requested grid, oldest first."},"proxy_wallet":{"type":"string","description":"The wallet the series was computed for."},"source_fidelity":{"type":"string","description":"Historical MVP observations are daily even when carried onto a finer grid."}}}}},"Envelope_UserVolume":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"object","description":"`/v2/user-volume`: one wallet's trading volume over a whole-day window, in\nboth units side by side.\n\n`volume` is both-sides SHARES; `volume_usdc` is the same measure in USD;\nthe bare name is the natural unit and `_usdc` is the denomination, the same\npairing as `current_size` / `entry_cost_usdc` on `/v2/positions`.\n`trade_count` is the number of trades in the window.","required":["volume","volume_usdc","trade_count"],"properties":{"trade_count":{"type":"integer","format":"int64","description":"Number of fills in the window.","minimum":0},"volume":{"type":"number","format":"double","description":"Both-sides traded volume over the window, in shares."},"volume_usdc":{"type":"number","format":"double","description":"Both-sides cash volume over the window, in USD."}}}}},"Envelope_Vec_BuilderVolumePoint":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One `/v2/builders/volume` row: a builder's volume in ONE bucket of the\nseries, not a running total.\n\n`date` is the bucket start (`YYYY-MM-DD`) and its width is the request's\n`interval`; daily, weekly, monthly, or yearly for `all`. `rank` is the\nbuilder's placing **within that bucket**, so it moves from bucket to bucket.\n`volume` is in SHARES, as on the leaderboard.","required":["date","rank","builder_name","builder_code","profile_image","verified","volume","active_users"],"properties":{"active_users":{"type":"integer","format":"int64","description":"Distinct active users attributed in that bucket.","minimum":0},"builder_code":{"type":"string","description":"Stable identifier of the builder."},"builder_name":{"type":"string","description":"Builder display name; cosmetic; key on `builder_code`."},"date":{"type":"string","description":"Bucket start date, `YYYY-MM-DD` (UTC); `interval` sets the width."},"profile_image":{"type":"string","description":"Builder profile image URL."},"rank":{"type":"integer","format":"int64","description":"Builder's rank within that bucket.","minimum":0},"verified":{"type":"boolean","description":"Whether the builder is verified."},"volume":{"type":"number","format":"double","description":"Volume attributed in that bucket, in shares."}}}}}},"Envelope_Vec_OpenInterest":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One `/v2/oi` row: the **priced gross** open interest of a market;\n`Σ ((shares − fee_receiver_shares)/1e6 · outcome_price)` across every\noutcome, with no netting. `condition_id` is the market's on-chain condition; the\nglobal shape carries `condition_id = \"GLOBAL\"`.","required":["condition_id","value"],"properties":{"condition_id":{"type":"string","description":"Condition id the row answers for; `GLOBAL` on the parameterless\nglobal figure."},"value":{"type":"number","format":"double","description":"Priced gross open interest in USDC; `0.0` when nothing is held."}}}}}},"Envelope_Vec_Resolution":{"type":"object","description":"`{ \"data\": T }`; the envelope for endpoints that don't paginate.\n\nThere is no `pagination` key: an aggregate or bounded list has no next page.\nPaginated feeds return a `*Page` shape (`{ data, pagination }`) instead.","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One non-paginated `/v2/resolutions` row. UMA lifecycle rows populate the\nnumeric-string price fields; direct question lookups omit `condition_id`,\nwhile condition/event lookups retain both the selected condition and backing\nUMA question. Native V2 and terminal CTF rows populate condition lifecycle,\npayout, provenance, and finality fields where those sources provide them.","required":["status","extended_review","was_disputed","new_version_q","transaction_hash","log_index","last_update_timestamp"],"properties":{"condition_id":{"type":["string","null"],"description":"Condition id the row answers for; absent on question-keyed rows."},"extended_review":{"type":"boolean","description":"True while a managed proposal sits past its normal expiry in extended\nreview; always false outside that window."},"last_update_timestamp":{"type":"string","description":"Latest lifecycle change: an epoch-seconds string on question-keyed\nrows, RFC3339 UTC on condition-keyed rows."},"log_index":{"type":"string","description":"Log index of the latest lifecycle event, as a numeric string; empty\nwhere `transaction_hash` is empty."},"market_type":{"type":["string","null"],"description":"BINARY, INCREMENTAL_NEGRISK or ATOMIC_NEGRISK; condition-keyed rows only."},"new_version_q":{"type":"boolean","description":"Whether the question rules were updated after posing."},"payouts":{"type":["array","null"],"items":{"type":"integer","format":"int64"},"description":"Per-outcome payout in micro-USDC per share, `[outcome0, outcome1]`;\npresent on resolved condition-keyed rows."},"price":{"type":["string","null"],"description":"Final settlement price, same conventions as `proposed_price`."},"proposed_price":{"type":["string","null"],"description":"Price of the first proposal as a numeric string; `69` means unset.\nPresent on question-keyed rows only."},"question_id":{"type":["string","null"],"description":"UMA question id serving the row; absent on condition-keyed rows."},"reporter":{"type":["string","null"],"description":"Reporter family that resolved it: UMA_OO, CHAINLINK or EOA."},"reproposed_price":{"type":["string","null"],"description":"Price of the second proposal, same conventions as `proposed_price`."},"resolution_source":{"type":["string","null"],"description":"`reported` (an oracle reported it) or `derived` (a neg-risk sibling\nresolution no client can reconstruct)."},"resolved_at":{"type":["string","null"],"description":"When the condition resolved, RFC3339 UTC."},"resolved_block":{"type":["integer","null"],"format":"int64","description":"Block the condition resolved at."},"status":{"type":"string","description":"Lifecycle state: initialized, posed, proposed, challenged, reproposed,\ndisputed or resolved; condition-keyed rows can also serve active and\narbitration."},"transaction_hash":{"type":"string","description":"Transaction of the latest lifecycle event; empty on condition-keyed\nrows without one."},"was_arbitrated":{"type":["boolean","null"],"description":"Whether arbitration was triggered on the request."},"was_disputed":{"type":"boolean","description":"Whether the resolution was disputed at any point."}}}}}},"ErrorResponse":{"type":"object","description":"Error body returned by Data API endpoints for unsuccessful requests.","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}}},"Holder":{"type":"object","description":"One `/v2/holders` row: a market holder enriched with their public profile,\nnetted across the market's outcome tokens by default or at per-side gross\ngrain with the position economics when `include_pnl=true`.\n`profile_image_optimized` is always empty.","required":["proxy_wallet","bio","token_id","pseudonym","amount","display_username_public","outcome_index","name","profile_image","profile_image_optimized","verified"],"properties":{"amount":{"type":"number","format":"double","description":"Holding in shares. By default the NET figure (a fully hedged wallet\nnets to `0.0` and only appears at `min_balance=0`); with\n`include_pnl=true` the per-side GROSS figure, so each side of a hedged\nwallet appears under its own token with that side's full size."},"avg_price":{"type":["number","null"],"format":"double","description":"Historical entry price per share. Served only with `include_pnl=true`."},"bio":{"type":"string","description":"Profile bio text."},"current_price":{"type":["number","null"],"format":"double","description":"Current price of the held outcome token, bounded to `[0, 1]`. Served\nonly with `include_pnl=true`."},"current_value":{"type":["number","null"],"format":"double","description":"Mark value of the holding: `amount` times `current_price`. Served only\nwith `include_pnl=true`."},"display_username_public":{"type":"boolean","description":"Whether the profile chose to show its name publicly."},"entry_cost_usdc":{"type":["number","null"],"format":"double","description":"Cost basis of the held size in USDC, excluding entry fees. Served only\nwith `include_pnl=true`."},"name":{"type":"string","description":"Profile display name of the wallet."},"outcome_index":{"type":"integer","format":"int32","description":"Index of the held outcome within the market; `999` means unlabelable."},"profile_image":{"type":"string","description":"Profile image URL."},"profile_image_optimized":{"type":"string","description":"Resized profile image URL, when one exists."},"proxy_wallet":{"type":"string","description":"The holding wallet."},"pseudonym":{"type":"string","description":"Generated fallback handle for profiles without a display name."},"realized_pnl":{"type":["number","null"],"format":"double","description":"Profit already locked in by sells and redemptions. Served only with\n`include_pnl=true`."},"token_id":{"type":"string","description":"Outcome token held."},"total_pnl":{"type":["number","null"],"format":"double","description":"Total profit and loss; always `realized_pnl + unrealized_pnl`. Served\nonly with `include_pnl=true`."},"unrealized_pnl":{"type":["number","null"],"format":"double","description":"Mark-to-market profit on the held size: `current_value` minus\n`entry_cost_usdc`. Served only with `include_pnl=true`."},"verified":{"type":"boolean","description":"Profile verification badge."}}},"HoldersPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/holders`; an offset-cursor\nfeed (per outcome token): the offset lives behind the opaque token,\nnever on the wire.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MetaHolder"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"IngestionFreshness":{"type":"object","description":"Ingestion health: one cursor per `(contract, event)` stream.\n\nEvery figure here is over the LIVE streams only. Streams that are dormant by\ndesign sit arbitrarily far behind forever; they are dropped outright rather\nthan reported and flagged, because there is nothing a consumer could do with\nthem and including them is precisely what makes the list useless.","required":["cursors","chain_id","lagging"],"properties":{"chain_id":{"type":"integer","format":"int64","description":"The chain id this service is configured for. Echoed so the pairing above\nis readable in one response."},"cursors":{"type":"integer","description":"How many live streams were found. `0` means no ingestion cursors are\nvisible to this API at all.","minimum":0},"lagging":{"type":"array","items":{"$ref":"#/components/schemas/CursorLag"},"description":"The furthest-behind live streams, `most_lagged` first."},"max_synced_block":{"type":["integer","null"],"format":"int64","description":"The tail: the furthest-along cursor. Every `behind_max` is measured\nagainst it, and so is each serving mechanism's `blocks_behind`."},"min_synced_block":{"type":["integer","null"],"format":"int64","description":"The furthest-behind LIVE stream's block. Deliberately asymmetric with\n`max_synced_block` above, which is over ALL cursors: the tail must not\nmove with the dormant cut, or excluding a stream would redefine the\ndistance every other stream is measured against."},"most_lagged":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CursorLag","description":"The single furthest-behind live stream. A stall confined to one stream\nwhile every sibling sits at head is invisible in any aggregate figure."}]},"network":{"type":["string","null"],"description":"The chain the ingestion cursors were written for, as the datastore\nitself names it; NOT as this service is configured. Compared against\n`chain_id`, it catches a datastore pointed at the wrong chain, which\notherwise presents as data that is merely wrong. `null` when no stream\ndeclares one."}}},"LeaderboardEntry":{"type":"object","description":"One `/v2/leaderboard` row: a user's standing on the ranked board.\n\n`pnl` is realized USDC over the window, base and combo positions unified.\n`volume` is both-sides SHARES, not USDC. `rank` is a competition\nrank; tied users share one, and the next rank skips.","required":["rank","user_id","pnl","volume","user_name","profile_image","x_username","verified"],"properties":{"pnl":{"type":"number","format":"double","description":"Window PnL in USDC. Finite windows (day/week/month) are the MARKED\nequity change net of flows; realized plus mark moves; `all` is the\nrealized-only lifetime ledger. The two deliberately differ."},"profile_image":{"type":"string","description":"Profile image URL."},"rank":{"type":"integer","format":"int32","description":"Rank on the requested board; ties share a rank and the next skips.","minimum":0},"user_id":{"type":"string","description":"The ranked wallet."},"user_name":{"type":"string","description":"Profile display name of the wallet."},"verified":{"type":"boolean","description":"Profile verification badge."},"volume":{"type":"number","format":"double","description":"Both-sides traded volume in shares; never USD."},"x_username":{"type":"string","description":"Linked X handle, when one exists."}}},"LeaderboardPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/leaderboard`; an offset-cursor\nboard. `rank` ties and skips, so the offset behind the token is the only\nsound way to page; never derive a page from a rank.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardEntry"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"LeaderboardResponse":{"oneOf":[{"$ref":"#/components/schemas/LeaderboardPage"},{"$ref":"#/components/schemas/Envelope_Option_LeaderboardUserEntry"}],"description":"Either arm's body. `?user=` answers with one standing; everything else with\na page of the board; genuinely different shapes, so the spec says `oneOf`\nrather than pretending one covers both."},"LeaderboardUserEntry":{"type":"object","description":"`/v2/leaderboard?user=`; one user's standing, carrying BOTH ranks.\n\nThe ranked board is materialised per sort, so it can only answer \"where does\nthis user place by PnL\" or \"by volume\", one at a time. This shape comes from\nthe by-user pivot instead and answers both at once.\n\nA `null` rank means **unranked** for that sort: the user exists in the pivot\nbut is filtered out of that board.","required":["user_id","pnl","volume","user_name","profile_image","x_username","verified"],"properties":{"pnl":{"type":"number","format":"double","description":"Window PnL in USDC, same semantics as the board rows (finite windows\nmarked, `all` realized-only)."},"profile_image":{"type":"string","description":"Profile image URL."},"rank_pnl":{"type":["integer","null"],"format":"int32","description":"`None` when unranked on the PnL board.","minimum":0},"rank_volume":{"type":["integer","null"],"format":"int32","description":"`None` when unranked on the volume board.","minimum":0},"user_id":{"type":"string","description":"The looked-up wallet."},"user_name":{"type":"string","description":"Profile display name of the wallet."},"verified":{"type":"boolean","description":"Profile verification badge."},"volume":{"type":"number","format":"double","description":"Both-sides traded volume in shares; never USD."},"x_username":{"type":"string","description":"Linked X handle, when one exists."}}},"LiveVolume":{"type":"object","description":"`/v2/live-volume`: one entry per market in the requested event(s), ordered\nby `taker_volume` descending, plus `taker_volume_total`; their sum. Events\nthat resolve to no markets serve `{ taker_volume_total: 0.0, conditions: [] }`.","required":["taker_volume_total","conditions"],"properties":{"conditions":{"type":"array","items":{"$ref":"#/components/schemas/ConditionVolume"},"description":"One row per market under the requested event(s), `taker_volume`\ndescending; empty when the events resolve to no markets."},"taker_volume_total":{"type":"number","format":"double","description":"Sum of the rows' `taker_volume`, in shares."}}},"MetaHolder":{"type":"object","description":"One outcome token's holder group in `/v2/holders`: the `token_id` and its\nholders, top-N by net balance. A multi-market request interleaves tokens\nacross the page, so merge groups by `token_id`, not by array position.","required":["token_id","holders"],"properties":{"holders":{"type":"array","items":{"$ref":"#/components/schemas/Holder"},"description":"Top holders of that token, amount descending (net by default,\nper-side gross with `include_pnl=true`)."},"token_id":{"type":"string","description":"The outcome token this group ranks."}}},"OpenInterest":{"type":"object","description":"One `/v2/oi` row: the **priced gross** open interest of a market;\n`Σ ((shares − fee_receiver_shares)/1e6 · outcome_price)` across every\noutcome, with no netting. `condition_id` is the market's on-chain condition; the\nglobal shape carries `condition_id = \"GLOBAL\"`.","required":["condition_id","value"],"properties":{"condition_id":{"type":"string","description":"Condition id the row answers for; `GLOBAL` on the parameterless\nglobal figure."},"value":{"type":"number","format":"double","description":"Priced gross open interest in USDC; `0.0` when nothing is held."}}},"Pagination":{"type":"object","required":["limit","offset","has_more"],"properties":{"has_more":{"type":"boolean","description":"Exact: `true` iff another page exists; probe-based, never inferred\nfrom page fullness."},"limit":{"type":"integer","format":"int32","description":"Page size this page was served with.","minimum":0},"next_cursor":{"type":["string","null"],"description":"Opaque, signed cursor for the next page; `null` on the last page."},"offset":{"type":"integer","format":"int32","description":"Running item offset for display continuity across keyset pages (the\ncursor drives the actual seek; this is cosmetic; there is no total).","minimum":0}}},"PortfolioValue":{"type":"object","description":"`/v2/value`: the user's portfolio value; single-market holdings marked to\nmarket plus unresolved combo positions at cost basis, rounded to 4 decimals. Always\nexactly one row; a user with no positions returns `{ proxy_wallet, value: 0 }`.","required":["proxy_wallet","value"],"properties":{"proxy_wallet":{"type":"string","description":"The wallet the value was computed for."},"value":{"type":"number","format":"double","description":"Portfolio value in USDC, rounded to 4 decimals: holdings marked to\nmarket plus non-terminal combos at cost basis."}}},"Position":{"type":"object","description":"One position (`/v2/positions`); a holding in a single outcome token, priced\nand enriched.\n\nThe shape is **uniform across all three arms** (user OPEN/REDEEMABLE, user\nCLOSED, market-anchored): clients never branch on which spine answered. On\nthe CLOSED arm `current_size`/`current_value`/`unrealized_pnl` are ~0 by construction, which is exactly\nwhat a closed position should report.\n\nKeyset-paginated on the active `sort_by` key: follow the response's\n`next_cursor` to page, and expect the ordering to change with `sort_by`.","required":["proxy_wallet","token_id","condition_id","current_size","avg_price","entry_cost_usdc","entry_fees_usdc","total_cost_usdc","current_price","current_value","total_size","realized_pnl","unrealized_pnl","total_pnl","percent_pnl","percent_realized_pnl","status","redeemable","mergeable","negative_risk","archived","title","slug","icon","event_id","event_slug","outcome","outcome_index","opposite_outcome","opposite_token_id","end_date","last_event_at","name","profile_image","verified"],"properties":{"archived":{"type":"boolean","description":"Whether the market is archived; tells a caller using `includeArchived`\nwhich rows the flag surfaced."},"avg_price":{"type":"number","format":"double","description":"Weighted-average entry price per share, in USDC."},"condition_id":{"type":"string","description":"The on-chain condition id."},"current_price":{"type":"number","format":"double","description":"Live mark per share, in USDC."},"current_size":{"type":"number","format":"double","description":"The CURRENT holding, in shares (~0 residual on the CLOSED arm)."},"current_value":{"type":"number","format":"double","description":"`current_size × current_price`, in USDC."},"end_date":{"type":"string","description":"Market end date, `YYYY-MM-DD`; `1970-01-01` when Gamma has none."},"entry_cost_usdc":{"type":"number","format":"double","description":"The fee-EXCLUSIVE entry basis."},"entry_fees_usdc":{"type":"number","format":"double","description":"Attributed BUY-fee total for the position. Disclosure only:\n`entry_cost_usdc` is already fee-exclusive, so never re-deduct this\nfrom a PnL column."},"event_id":{"type":"string","description":"Gamma event id of the parent event."},"event_slug":{"type":"string","description":"Parent event slug."},"icon":{"type":"string","description":"Market icon URL."},"last_event_at":{"type":"integer","format":"int64","description":"The row's last economics event, epoch seconds; 0 without native state."},"mergeable":{"type":"boolean","description":"Whether the wallet also holds the opposite outcome, so the pair can\nmerge back into collateral."},"name":{"type":"string","description":"Profile display name of the wallet."},"negative_risk":{"type":"boolean","description":"Whether the market belongs to a neg-risk group."},"opposite_outcome":{"type":"string","description":"Label of the market's other outcome; what a merge pairs with."},"opposite_token_id":{"type":"string","description":"Token id of the market's other outcome."},"outcome":{"type":"string","description":"Label of the held outcome (e.g. `Yes`)."},"outcome_index":{"type":"integer","format":"int32","description":"Index of the held outcome within the market; `999` means the outcome\ncould not be labeled."},"percent_pnl":{"type":"number","format":"double","description":"`(current_value - entry_cost_usdc) / entry_cost_usdc`, as a percent.\nFee-exclusive basis, and the numerator is `unrealized_pnl`; not\n`total_pnl / total_cost_usdc`."},"percent_realized_pnl":{"type":"number","format":"double","description":"`(current_value - total_size × avg_price) / (total_size × avg_price)`,\nas a percent. A compatibility shape: despite the name, it is not\n`realized_pnl` over a basis."},"profile_image":{"type":"string","description":"Profile image URL."},"proxy_wallet":{"type":"string","description":"Proxy wallet holding the position."},"realized_pnl":{"type":"number","format":"double","description":"Realized PnL in USDC, cumulative for the position."},"redeemable":{"type":"boolean","description":"Whether the position can be redeemed now: its market resolved and the\ntokens are still held (losing sides included; redeemable ≠ won)."},"slug":{"type":"string","description":"Market slug; the URL segment on polymarket.com."},"status":{"type":"string","description":"The row's actual state; can be narrower than the requested `status`,\nsince an `OPEN` request also returns `REDEEMABLE` rows."},"title":{"type":"string","description":"Market question title (Gamma enrichment; empty when unenriched)."},"token_id":{"type":"string","description":"The outcome token id."},"total_cost_usdc":{"type":"number","format":"double","description":"Gross (fee-INCLUSIVE) basis. Always exactly\n`entry_cost_usdc + entry_fees_usdc`; the contract sums the two served\ncolumns, so the identity holds on every row of every arm."},"total_pnl":{"type":"number","format":"double","description":"Always equals `realized_pnl + unrealized_pnl`."},"total_size":{"type":"number","format":"double","description":"LIFETIME bought shares (the WAC denominator), never the\ncurrent balance; that is `current_size`."},"unrealized_pnl":{"type":"number","format":"double","description":"Unrealized (mark-to-market) PnL: `current_value - entry_cost_usdc`."},"verified":{"type":"boolean","description":"Profile verification badge."}}},"PositionsPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/positions`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Position"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"PricePoint":{"type":"object","description":"One served point.","required":["timestamp","price","resolution_seconds"],"properties":{"price":{"type":"number","format":"double","description":"Price in the range 0…1. Always a JSON number."},"resolution_seconds":{"type":"integer","format":"int64","description":"Width of the window this price was observed in: `0` for an exact tick,\nthe bucket width for an aggregate. So the price was observed within\n`[timestamp, timestamp + resolution_seconds)`, and a caller can tell\nwhether that is precise enough.\n\nPer-point rather than per-response because points in one response\ngenuinely differ: grid points carry the requested bucket width, the\nseries' terminal point is an exact tick at `0`, and a tier-degraded\n`as_of` carries its tier's width.\n\nThis is the ONLY thing the payload says about provenance, deliberately."},"timestamp":{"type":"integer","format":"int64","description":"The OBSERVATION's own time, epoch seconds, never the time that was\nasked for. A raw tick reports the tick; an aggregate reports its bucket\nstart."}}},"PricesHistoryPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/prices-history`. The terminal\npoint (the latest observation inside the window) is part of the series\nand lands on the final page, so a client that wants the freshest value\non a multi-page series follows the cursor to the end.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PricePoint"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"Resolution":{"type":"object","description":"One non-paginated `/v2/resolutions` row. UMA lifecycle rows populate the\nnumeric-string price fields; direct question lookups omit `condition_id`,\nwhile condition/event lookups retain both the selected condition and backing\nUMA question. Native V2 and terminal CTF rows populate condition lifecycle,\npayout, provenance, and finality fields where those sources provide them.","required":["status","extended_review","was_disputed","new_version_q","transaction_hash","log_index","last_update_timestamp"],"properties":{"condition_id":{"type":["string","null"],"description":"Condition id the row answers for; absent on question-keyed rows."},"extended_review":{"type":"boolean","description":"True while a managed proposal sits past its normal expiry in extended\nreview; always false outside that window."},"last_update_timestamp":{"type":"string","description":"Latest lifecycle change: an epoch-seconds string on question-keyed\nrows, RFC3339 UTC on condition-keyed rows."},"log_index":{"type":"string","description":"Log index of the latest lifecycle event, as a numeric string; empty\nwhere `transaction_hash` is empty."},"market_type":{"type":["string","null"],"description":"BINARY, INCREMENTAL_NEGRISK or ATOMIC_NEGRISK; condition-keyed rows only."},"new_version_q":{"type":"boolean","description":"Whether the question rules were updated after posing."},"payouts":{"type":["array","null"],"items":{"type":"integer","format":"int64"},"description":"Per-outcome payout in micro-USDC per share, `[outcome0, outcome1]`;\npresent on resolved condition-keyed rows."},"price":{"type":["string","null"],"description":"Final settlement price, same conventions as `proposed_price`."},"proposed_price":{"type":["string","null"],"description":"Price of the first proposal as a numeric string; `69` means unset.\nPresent on question-keyed rows only."},"question_id":{"type":["string","null"],"description":"UMA question id serving the row; absent on condition-keyed rows."},"reporter":{"type":["string","null"],"description":"Reporter family that resolved it: UMA_OO, CHAINLINK or EOA."},"reproposed_price":{"type":["string","null"],"description":"Price of the second proposal, same conventions as `proposed_price`."},"resolution_source":{"type":["string","null"],"description":"`reported` (an oracle reported it) or `derived` (a neg-risk sibling\nresolution no client can reconstruct)."},"resolved_at":{"type":["string","null"],"description":"When the condition resolved, RFC3339 UTC."},"resolved_block":{"type":["integer","null"],"format":"int64","description":"Block the condition resolved at."},"status":{"type":"string","description":"Lifecycle state: initialized, posed, proposed, challenged, reproposed,\ndisputed or resolved; condition-keyed rows can also serve active and\narbitration."},"transaction_hash":{"type":"string","description":"Transaction of the latest lifecycle event; empty on condition-keyed\nrows without one."},"was_arbitrated":{"type":["boolean","null"],"description":"Whether arbitration was triggered on the request."},"was_disputed":{"type":"boolean","description":"Whether the resolution was disputed at any point."}}},"ServiceStatus":{"type":"object","description":"`/v2/status` payload.\n\nServed from a snapshot refreshed in the background, never computed on the\nrequest. `computed_at`/`age_seconds` make that explicit rather than implicit:\nif the refresher wedges or its datastore goes away, the answer keeps being\nserved with a growing age instead of turning into a 500; the right degraded\nmode for the endpoint you call when something is already wrong.","required":["computed_at","age_seconds","serving","ingestion"],"properties":{"age_seconds":{"type":"integer","format":"int64","description":"How old the snapshot is, in seconds. Normally under the refresh\ninterval; a value that keeps climbing means the refresher is not\ncompleting, and the freshness figures below are that stale ON TOP of\nwhatever lag they report."},"computed_at":{"type":"string","description":"When this snapshot was taken, RFC 3339 in UTC."},"ingestion":{"$ref":"#/components/schemas/IngestionFreshness"},"serving":{"$ref":"#/components/schemas/ServingFreshness"}}},"ServingFreshness":{"type":"object","description":"What API consumers actually experience: the projections behind the feeds.\n\nOne headline number and the name of whichever mechanism produced it, so a\nsingle stalled projection cannot hide behind two healthy ones; the same\nshape as `ingestion.most_lagged`, for the same reason.","required":["mechanisms"],"properties":{"lag_seconds":{"type":["integer","null"],"format":"int64","description":"The worst age across `mechanisms`. `null` only when no mechanism\nreported at all."},"mechanisms":{"type":"array","items":{"$ref":"#/components/schemas/ServingMechanism"},"description":"Every mechanism that produced a candidate freshness row, in a fixed\norder; `worst` names the culprit."},"worst":{"type":["string","null"],"description":"Which mechanism `lag_seconds` came from."}}},"ServingMechanism":{"type":"object","description":"One serving mechanism's freshness.","required":["name","age_seconds"],"properties":{"age_seconds":{"type":"integer","format":"int64","description":"Seconds since it last advanced, by its own clock."},"blocks_behind":{"type":["integer","null"],"format":"int64","description":"How far behind the ingestion tail it has projected. Absent for a\nmechanism that records a time but no block."},"name":{"type":"string","description":"What this mechanism produces: `activity_feed`, `custody_balances`, `pnl`."}}},"Trade":{"type":"object","description":"A trade (`/v2/trades`).","required":["proxy_wallet","side","token_id","condition_id","size","price","timestamp","title","slug","icon","event_slug","outcome","outcome_index","name","pseudonym","bio","profile_image","profile_image_optimized","transaction_hash"],"properties":{"bio":{"type":"string","description":"Profile bio text."},"condition_id":{"type":"string","description":"On-chain condition id of the market (`0x` hex)."},"event_slug":{"type":"string","description":"Parent event slug."},"icon":{"type":"string","description":"Market icon URL."},"name":{"type":"string","description":"Profile display name of the wallet."},"outcome":{"type":"string","description":"Label of the traded outcome (e.g. `Yes`)."},"outcome_index":{"type":"integer","format":"int32","description":"Index of the traded outcome within the market; `999` means the\noutcome could not be labeled."},"price":{"type":"number","format":"double","description":"Execution price per share, in USDC."},"profile_image":{"type":"string","description":"Profile image URL."},"profile_image_optimized":{"type":"string","description":"Resized profile image URL, when one exists."},"proxy_wallet":{"type":"string","description":"Proxy wallet the row belongs to; the address every wallet-keyed\nendpoint accepts as `user`."},"pseudonym":{"type":"string","description":"Generated fallback handle for profiles without a display name."},"side":{"type":"string","description":"`BUY` or `SELL`, from this wallet's perspective."},"size":{"type":"number","format":"double","description":"Filled quantity in shares; bare sizes are shares, never USD."},"slug":{"type":"string","description":"Market slug; the URL segment on polymarket.com."},"timestamp":{"type":"integer","format":"int64","description":"Block timestamp of the fill, epoch seconds."},"title":{"type":"string","description":"Market question title (Gamma enrichment; empty when unenriched)."},"token_id":{"type":"string","description":"CLOB asset id of the traded outcome token."},"transaction_hash":{"type":"string","description":"Hash of the settling transaction."}}},"TradesPage":{"type":"object","description":"`{ data, pagination }` envelope for `/v2/trades`.","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Trade"},"description":"The page's rows."},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Paging envelope: follow `next_cursor` until `null`."}}},"UserPnlPoint":{"type":"object","description":"One dense cumulative v2 chart point in USDC.\n\nNullable values mean the historical source or mark was unavailable. Clients\nmust not coerce them to zero.","required":["timestamp","source_block","realized_market_pnl","realized_lp_pnl","realized_combo_pnl","realized_pnl","volume","volume_usdc","trade_count"],"properties":{"cashflow_net":{"type":["number","null"],"format":"double","description":"`deposits - withdrawals`."},"deposits":{"type":["number","null"],"format":"double","description":"Collateral moved into the wallet."},"economic_pnl":{"type":["number","null"],"format":"double","description":"`position_pnl + wallet_income`; the all-in economic result."},"fees":{"type":["number","null"],"format":"double","description":"Negative cumulative fee charges, for direct chart composition."},"fees_paid":{"type":["number","null"],"format":"double","description":"Refunds minus charges; a disclosure, not another PnL adjustment."},"fees_refunded":{"type":["number","null"],"format":"double","description":"Fee atom: total fees refunded."},"maker_rebate":{"type":["number","null"],"format":"double","description":"Maker-side fee rebates credited."},"position_pnl":{"type":["number","null"],"format":"double","description":"`realized_pnl + unrealized_pnl`; the position-only result."},"realized_combo_pnl":{"type":"number","format":"double","description":"Realized PnL from combo positions."},"realized_lp_pnl":{"type":"number","format":"double","description":"Realized PnL from AMM liquidity-provision activity."},"realized_market_pnl":{"type":"number","format":"double","description":"Realized PnL from market positions."},"realized_pnl":{"type":"number","format":"double","description":"`realized_market_pnl + realized_lp_pnl + realized_combo_pnl`."},"referral_income":{"type":["number","null"],"format":"double","description":"Referral income credited."},"reward_income":{"type":["number","null"],"format":"double","description":"Reward-program income credited."},"settled_pnl":{"type":["number","null"],"format":"double","description":"`realized_pnl + wallet_income`; settled economics, no marks."},"source_block":{"type":"integer","format":"int64","description":"Chain block the point was observed at."},"sponsored_income":{"type":["number","null"],"format":"double","description":"`reward_income + yield_income + referral_income`."},"taker_rebate":{"type":["number","null"],"format":"double","description":"Taker-side fee rebates credited."},"timestamp":{"type":"integer","format":"int64","description":"Point timestamp, in epoch seconds. Every amount below is CUMULATIVE\nthrough this instant, in USDC; `null` means the source is uncovered,\nnever zero."},"trade_count":{"type":"integer","format":"int64","description":"Cumulative maker-attributed canonical exchange fill count.","minimum":0},"trade_pnl":{"type":["number","null"],"format":"double","description":"`position_pnl - realized_lp_pnl + fees_charged - fees_refunded`; the\ncompatibility chart series (`p` on the bare user-pnl route)."},"unrealized_pnl":{"type":["number","null"],"format":"double","description":"Mark-to-market of open inventory."},"volume":{"type":"number","format":"double","description":"Cumulative maker-attributed canonical exchange fill shares."},"volume_usdc":{"type":"number","format":"double","description":"Cumulative maker-attributed canonical exchange fill cash in USDC."},"wallet_income":{"type":["number","null"],"format":"double","description":"All income credited to the wallet: rebates (maker + taker) plus\nreward, yield and referral income."},"withdrawals":{"type":["number","null"],"format":"double","description":"Collateral moved out of the wallet."},"yield_income":{"type":["number","null"],"format":"double","description":"Yield income credited."}}},"UserPnlSeries":{"type":"object","description":"Complete v2 user-PnL response data.","required":["proxy_wallet","interval","fidelity","source_fidelity","points"],"properties":{"fidelity":{"type":"string","description":"Grid step the points were synthesized on (`1d`, `18h`, `12h`, `3h`, `1h`)."},"interval":{"type":"string","description":"The window served (`max`, `all`, `1m`, `1w`, `1d`, `12h`, `6h`)."},"points":{"type":"array","items":{"$ref":"#/components/schemas/UserPnlPoint"},"description":"Dense cumulative points on the requested grid, oldest first."},"proxy_wallet":{"type":"string","description":"The wallet the series was computed for."},"source_fidelity":{"type":"string","description":"Historical MVP observations are daily even when carried onto a finer grid."}}},"UserStats":{"type":"object","description":"The profile card for one wallet, plus its newest persisted all-time PnL\nobservation.\n\n`join_date` is `null` when unknown, which is a real state rather than an\nerror; a meaningful share of accounts have no recorded creation time.\n`biggest_win` is `0` when the wallet has no win over $1. `all_time_pnl` is\n`null` when the user is known but has no observation yet; a missing user is\nrepresented by the outer response `data: null` instead.","required":["proxy_wallet","trades","biggest_win","views"],"properties":{"all_time_pnl":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UserPnlPoint","description":"Newest persisted cumulative all-time PnL point, or `null` when absent."}]},"biggest_win":{"type":"number","format":"double","description":"Largest single resolved win, in USDC."},"join_date":{"type":["integer","null"],"format":"int64","description":"Epoch seconds, or `null` when the join date is unknown."},"proxy_wallet":{"type":"string","description":"The proxy wallet these lifetime statistics describe."},"trades":{"type":"integer","format":"int64","description":"Distinct markets the wallet traded; an exact count.","minimum":0},"views":{"type":"integer","format":"int64","description":"Profile view count.","minimum":0}}},"UserVolume":{"type":"object","description":"`/v2/user-volume`: one wallet's trading volume over a whole-day window, in\nboth units side by side.\n\n`volume` is both-sides SHARES; `volume_usdc` is the same measure in USD;\nthe bare name is the natural unit and `_usdc` is the denomination, the same\npairing as `current_size` / `entry_cost_usdc` on `/v2/positions`.\n`trade_count` is the number of trades in the window.","required":["volume","volume_usdc","trade_count"],"properties":{"trade_count":{"type":"integer","format":"int64","description":"Number of fills in the window.","minimum":0},"volume":{"type":"number","format":"double","description":"Both-sides traded volume over the window, in shares."},"volume_usdc":{"type":"number","format":"double","description":"Both-sides cash volume over the window, in USD."}}}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}}},"security":[{"bearer":[]}],"tags":[{"name":"wallet","description":"Everything anchored on one wallet: positions (base and combos), portfolio value, PnL history, the profile card, trading volume, and token approvals. Pass the proxy wallet as `user`. One exception cuts across sections: `/v2/positions` with `condition` alone (no `user`) answers the market-wide holders question."},{"name":"feeds","description":"The high-traffic keyset feeds: trades, activity and combo activity. Filter by `user`, `condition` or `event_id`; page with `next_cursor`."},{"name":"markets","description":"Market and event state, keyed by on-chain `condition` ids, Gamma `event_id`s or a CLOB `token_id`: open interest, holders, per-event taker volume, resolution lifecycle, and price history."},{"name":"boards","description":"Ranked, windowed boards: the PnL/volume leaderboard, biggest single wins, and the builder standings and volume buckets. Cursors pin the board they were minted on."},{"name":"service","description":"Service metadata: data freshness: the serving watermark, its lag, and per-stream ingestion cursors."}]}