Skip to main content
GET
Use this endpoint to see which graded wallets hold each side of a market. It lists S, A, and B wallets with open shares, ordered by current position value, and uses the same holder list as the Pick of the Day. For a wallet’s holdings across markets, use Positions. For recently changed positions worth at least $50,000, use Large positions.

Parameters

Key response fields

Rows are ordered by current_value_usd from largest, then by shares from largest, then by address alphabetically.

Paging and refreshes

The holder list refreshes at most once per minute per market and is shared across callers. Its Polymarket scan is reused for 180 seconds. New cursors carry the next holder’s position independently of limit, so changing page size on the same roster does not skip or repeat rows. Raw condition IDs and their mkt_ forms identify the same market, and omitted outcome and min_grade match all and B. Existing page-number cursors remain accepted without a scheduled retirement. Keep the original limit when using one; its next response returns the new format. Treat every cursor as opaque. A cursor remains valid when the holder list refreshes. It identifies a position in the current list, so changes between requests can repeat or skip a holder. Restart without a cursor if you change filters.

Example

What it does not return

  • An ungraded wallet, whatever min_grade says. scan.wallet_count is the only trace they leave.
  • A partial list. A Polymarket scan that came back incomplete, unstable, or failed, or that ran past its 20-second budget, returns 503 with error.reason read_model_warming and a Retry-After.
  • A rate limit under that 503. Retry this one route after Retry-After, and keep the retry separate from rate-limit handling.
  • A market Polymarket does not have. That id returns 404.
  • Trade history. Each row carries the wallet’s current position, not the trades that built it.

Caching

Save the response’s ETag and send it in If-None-Match on your next request. If the page has not changed, the server returns 304 Not Modified with no body.

Authorizations

Authorization
string
header
required

Legacy default or named integration API key, or OAuth 2.1 access token, in the Authorization header as Bearer oxi_sk_live_... or Bearer oxi_at_.... Default keys retain full access; integration keys are limited to their approved read, webhooks, export and usage scopes and expire within 90 days. All credentials share the owner's account limits. Data calls require an active Pro subscription and return live data. A 401 carries WWW-Authenticate: Bearer resource_metadata="https://api.0xinsider.com/.well-known/oauth-protected-resource" (RFC 6750 section 3, RFC 9728).

Headers

X-Query-Validation
enum<string>

Opt into strict query-name validation. The default is compatible: unknown names are ignored and reported in X-Query-Ignored. With strict, an unknown name returns 400 bad_request with error.reason unknown_query_parameter before the handler runs, including when its percent escape is incomplete.

Available options:
strict
If-None-Match
string

Conditional GET validator from a previous ETag. Matching values return 304 Not Modified with an empty body.

Path Parameters

condition_id
string
required

Market condition ID. Accepts the raw provider-backed condition_id returned by /api/v1/markets/search or the mkt_-prefixed market.id emitted by V1 responses.

Query Parameters

outcome
enum<string>
default:all

Keep holders netting one side. all (default) lists both.

Available options:
yes,
no,
all
min_grade
enum<string>
default:B

Narrow within the graded cohort: S keeps S, A keeps S and A, B (default) keeps S, A and B. C, D and F are rejected with 400: the route lists the S/A/B cohort only. The cohort is the wallet's current grade (traders.latest_grade), so no value here reaches a C, D, F or ungraded holder; those are counted only in scan.wallet_count. min_grade=D on GET /api/v1/positions does return C and D, which is one of the three reasons the two routes' counts differ for the same market.

Available options:
S,
A,
B
limit
integer
default:20

Maximum holders per page. Out-of-range values are clamped to 1..100.

Required range: 1 <= x <= 100
cursor
string

Opaque pagination cursor from the previous response's next_cursor. New cursors carry an absolute next offset bound to normalized condition_id, outcome and effective min_grade, so limit can change without skipping or repeating rows on the same roster. Different market/filter bindings return 400 bad_request with param=cursor; omitted filters match all/B and mkt_-prefixed IDs match their raw condition_id. Legacy page-only cursors remain accepted without scheduled retirement and require their original limit; their next response emits the new format. A cursor remains valid across roster refreshes, which can still repeat or skip holders as the live roster changes.

Response

One page of the market's graded holder roster.

object
string
required
Allowed value: "list"
data
object[]
required
has_more
boolean
required
market
object
required
scan
object
required
totals
object
required

Roster totals BEFORE any outcome or min_grade filter, so a page always knows the whole market it was cut from.

meta
object
required
next_cursor
string

Absent on the last page.

total
integer

Holders matching the request's outcome and min_grade filters across every page.