API · Reference

Quick answer (updated 2026-10-25)

The Polymarket Data API is public and needs no key. Use version 2 at https://data-api.polymarket.com/v2: /v2/positions?user=<wallet> for a wallet's positions and PnL, /v2/trades for trade history, /v2/activity for trades, splits, merges, redemptions and rewards, /v2/value for portfolio value, /v2/holders?condition= for a market's top holders and /v2/leaderboard for the trader leaderboard. Every v2 response wraps results in data and pages with pagination.next_cursor. Pass the account wallet address (the proxy_wallet), not the signing key. Polymarket's docs mark the old v1 routes retired from 24 October 2026.

The Data API answers "who holds what and what happened": positions, profit and loss, trade and activity feeds, holders, open interest and leaderboards, for any wallet or market, with nothing more than an HTTP GET. This page lists every v2 endpoint with its parameters, shows real responses, gives Python and TypeScript code for the official SDKs, and maps the old v1 routes to v2. Polymarkets.co.il is an independent guide, not Polymarket. Everything was checked on 25 October 2026 against Polymarket's developer documentation and the published v2 OpenAPI contract, and the endpoints were called live to confirm their shape.

What this page answers

  • The Data API base URL, and whether it needs an API key
  • Every v2 endpoint: positions, trades, activity, value, holders, leaderboard and more
  • Which wallet address to pass (proxy wallet vs signing key)
  • Cursor pagination, units and rate limits
  • Moving from v1 (/positions, /activity) to v2

Polymarket Data API endpoints (v2)

Base URL https://data-api.polymarket.com; every route below starts with /v2. No API key, no signature, no account. The full machine-readable contract is published at data-api.polymarket.com/v2/openapi.json.

EndpointReturnsKey parameters
GET /v2/positionsA wallet's or a market's positions, with cost basis and PnLuser or condition (one required), status, sort_by, title, limit (max 1000)
GET /v2/valuePortfolio value of a walletuser (required), condition
GET /v2/tradesTrades for a wallet, market, event, or the global feeduser, condition, event_id, side, start, end, taker_only
GET /v2/activityEverything a wallet did: trades, splits, merges, redemptions, rewards, rebates, depositsuser, type, condition, start, end, limit (default 100, max 1000)
GET /v2/holdersA market's top holders per outcomecondition (required), limit, include_pnl
GET /v2/leaderboardTrader leaderboard by PnL or volumetime_period, category, sort_by, user
GET /v2/biggest-winnersLargest single winning positionstime_period, category
GET /v2/user-pnlA wallet's cumulative PnL seriesuser, interval, fidelity
GET /v2/user-statsProfile stats, including the number of markets tradeduser
GET /v2/user-volumeA wallet's trading volume over a windowuser, start, end
GET /v2/approvalsA wallet's token and operator approvals on Polygonuser
GET /v2/oiOpen interest per marketcondition
GET /v2/live-volumeLive volume for an eventevent_id
GET /v2/prices-historyOne outcome token's price historytoken_id, interval or start/end or as_of, bucket_seconds
GET /v2/resolutionsResolution state (proposals, disputes, settlement estimates)condition, event_id, question_id
GET /v2/tokensToken IDs or conditions mapped to markets and outcomestoken_id (up to 50) or condition
GET /v2/positions/combos, /v2/activity/combosCombo positions and combo activityuser
GET /v2/builders/leaderboard, /v2/builders/volumeBuilder rankings and volume over timetime_period, interval
GET /v2/statusData freshness (how far behind the chain the API is)None

/v2/positions: a wallet's positions and PnL

The workhorse. Pass a wallet with user= to get its open positions, each with cost basis and profit and loss already computed; pass condition= instead to list a market's positions.

curl -s "https://data-api.polymarket.com/v2/positions?user=$WALLET&limit=1"

Real response (25 October 2026, trimmed):

{
  "data": [
    {
      "proxy_wallet": "0x983eedfb...6748",
      "token_id": "2032407043...6504",
      "condition_id": "0xf74a1dd0...feb8",
      "current_size": 12000.0,
      "avg_price": 0.38,
      "entry_cost_usdc": 4560.0,
      "entry_fees_usdc": 141.36,
      "current_price": 0.0,
      "current_value": 0.0,
      "realized_pnl": -141.36,
      "unrealized_pnl": -4560.0,
      "total_pnl": -4701.36,
      "status": "REDEEMABLE",
      "redeemable": true,
      "mergeable": false,
      "negative_risk": true,
      "title": "Will Genoa CFC win on 2026-09-20?",
      "outcome": "Yes",
      "outcome_index": 0,
      "opposite_token_id": "4853053701...1490",
      "first_entry_at": 1789907647,
      "last_event_at": 1789917433
    }
  ],
  "pagination": { "limit": 1, "offset": 0, "has_more": true, "next_cursor": "eyJkYXRh..." }
}
FieldMeaning
token_idThe outcome token: pass it to the CLOB to read the book or trade
current_size, avg_priceShares held and average entry price
entry_cost_usdc, entry_fees_usdcEntry cost without fees, and the buy fees on top
realized_pnl, unrealized_pnl, total_pnlProfit and loss in USD; total = realized + unrealized
statusOPEN, REDEEMABLE (resolved, can be claimed), MERGEABLE or CLOSED

Filter with status: OPEN (the default), REDEEMABLE, REDEEMABLE_LOST (held losing positions), MERGEABLE (complete Yes and No pairs) or CLOSED (fully exited positions with their realized PnL). Sort with sort_by: CURRENT_VALUE, PRICE, TOKENS, UNREALIZED_PNL, REALIZED_PNL, TOTAL_PNL or TIMESTAMP.

Which address to pass: the proxy wallet, not the signing key

Polymarket accounts trade from an account wallet (a Deposit Wallet for accounts created since May 2026, or an older Proxy Wallet or Safe) that is different from the key that signs. That account wallet is what holds positions, what polymarket.com shows in the profile menu, and what the Data API returns as proxy_wallet. Pass it as user. Querying the signing key (the EOA) usually returns an empty list. To find a trader's wallet, take proxy_wallet from /v2/trades, /v2/holders or /v2/leaderboard (where it appears as user_id). Wallet types are explained in authentication and wallets.

/v2/trades: trade history

Every fill, newest first. With user= it is one wallet's history; with condition= or event_id= one market or event; with neither, the global feed. By default (taker_only=true) each fill appears once, on the taker's side; taker_only=false adds the maker rows.

curl -s "https://data-api.polymarket.com/v2/trades?user=$WALLET&limit=100"
{
  "data": [
    { "proxy_wallet": "0x53805554...4b3", "side": "SELL", "token_id": "5448579069...0081",
      "condition_id": "0x2093b156...1be8", "size": 0.35, "price": 0.61, "timestamp": 1792951041,
      "title": "Bitcoin Up or Down - October 25, 1:45PM-2:00PM ET", "outcome": "Up",
      "transaction_hash": "0xa39fe4d9...f730" }
  ],
  "pagination": { "limit": 1, "offset": 0, "has_more": true, "next_cursor": "eyJkYXRh..." }
}

Timestamps are Unix seconds. transaction_hash lets you verify the trade on a Polygon block explorer.

/v2/activity: the full on-chain action log

Trades are only part of what a wallet does. /v2/activity returns every action, filtered with type (comma-separated): TRADE, SPLIT, MERGE, REDEEM, CONVERSION, MIGRATION, REWARD, YIELD, MAKER_REBATE, TAKER_REBATE, REFERRAL_REWARD, DEPOSIT, WITHDRAWAL or TIP. Leaving type out returns everything except tips.

curl -s "https://data-api.polymarket.com/v2/activity?user=$WALLET&type=SPLIT,MERGE,REDEEM&limit=50"

Two details catch people out. An omitted start only reaches back three years; send start=1 for the full history. And a redemption appears as one row per outcome, so redeeming both sides of a market gives two rows (sum usdc_size for the payout). Split, merge and redeem are explained in the CLOB guide.

/v2/value: portfolio value

curl -s "https://data-api.polymarket.com/v2/value?user=$WALLET"
{ "data": { "proxy_wallet": "0x983eedfb...6748", "value": 0.0 } }

The value marks single-market holdings to market and counts unresolved combo positions at cost. Add condition= (up to 20 IDs) to value only some markets.

/v2/holders: who holds a market

curl -s "https://data-api.polymarket.com/v2/holders?condition=$CONDITION_ID&limit=20"

Returns the top holders for each outcome token, netted per wallet; limit applies per token (default 100, max 1000). With include_pnl=true (one market at a time, up to 100 rows) each holder also gets average price, entry cost and PnL, which is useful for spotting concentrated or underwater positions.

/v2/leaderboard: the trader leaderboard endpoint

curl -s "https://data-api.polymarket.com/v2/leaderboard?time_period=week&sort_by=PNL&limit=10"
{ "data": [ { "rank": 1, "user_id": "0x57a85952...ebc2", "pnl": 1460154.79, "volume": 832550.81,
              "user_name": "...", "verified": false } ],
  "pagination": { "limit": 2, "offset": 0, "has_more": true, "next_cursor": "eyJkYXRh..." } }

time_period is day (default), week, month or all; sort_by is PNL (default) or VOLUME; category is overall (default), a market category such as sports, or combos / esports. Add user= to look up one wallet's standing.

Python and TypeScript: the official SDKs

The unified SDKs, polymarket-client 0.14.0 (Python) and @polymarket/client 0.14.0 (TypeScript), call Data API v2 since version 0.10.0, handle cursors for you and need no key for these reads.

Python

# pip install polymarket-client
import asyncio
from polymarket import AsyncPublicClient

WALLET = "0x..."   # the account (proxy) wallet

async def main():
    async with AsyncPublicClient() as client:
        page = await client.list_positions(user=WALLET, page_size=50).first_page()
        for p in page.items:
            print(p.title, p.outcome, p.current_size, "PnL", p.total_pnl)

        value = await client.get_portfolio_value(user=WALLET)
        print("portfolio value", value)

        async for item in client.list_activity(user=WALLET, page_size=100).iter_items():
            print(item)
            break                                   # remove to walk the full history

asyncio.run(main())

TypeScript

// npm install @polymarket/client@latest
import { createPublicClient } from "@polymarket/client";

const client = createPublicClient();
const wallet = "0x...";   // the account (proxy) wallet

const page = await client.listPositions({ user: wallet, pageSize: 50 }).firstPage();
for (const p of page.items) console.log(p.title, p.outcome, p.currentSize, "PnL", p.totalPnl);

const value = await client.fetchPortfolioValue({ user: wallet });
console.log("portfolio value", value.value);

Plain HTTP with cursor pagination

import requests

def walk(path, **params):
    url = "https://data-api.polymarket.com" + path
    cursor = None
    while True:
        q = dict(params, cursor=cursor) if cursor else params
        r = requests.get(url, params=q, timeout=20)
        r.raise_for_status()
        body = r.json()
        yield from body["data"] or []
        cursor = body["pagination"]["next_cursor"]
        if not cursor:
            break

for t in walk("/v2/trades", user="0x...", limit=500):
    print(t["timestamp"], t["side"], t["size"], t["price"], t["title"])

Rules from the docs: there is no offset parameter (v2 rejects it with a 400); stop when next_cursor is null, not when a page looks short; on /v2/trades and /v2/activity resend the same filters with every cursor; and after the first page the cursor's own page size wins over limit.

Units, pagination and rate limits

  • Envelope: every response is { "data": ..., "pagination": {...} }. A miss is data: null or an empty list, not an error.
  • Units: plain size and volume are shares; fields ending in _usdc are US dollars; all amounts are JSON numbers. outcome_index: 999 means the outcome could not be labelled.
  • IDs: markets are selected with condition (aliases condition_id, conditionId), up to 20 per request. Parameters accept snake_case or camelCase.
  • Rate limits (per IP, 25 Oct 2026): 800 requests per 10 s across /v2; /v2/trades 300; /v2/positions and /v2/activity 200 each. Under load the API answers 429 with a Retry-After header.
  • Freshness: /v2/status reports how many seconds and blocks the data trails Polygon (a few seconds when we checked).

Data API v1 to v2: route mapping

Polymarket's migration guide states that Data API v1 is retired on 24 October 2026; only GET /v1/accounting/snapshot stays. When we checked on 25 October 2026 the v1 /positions and /value routes still answered, but build on v2: v1 is frozen and can stop at any time.

v1 routev2 route
/positions/v2/positions (market becomes condition)
/closed-positions/v2/positions?status=CLOSED
/v1/market-positions/v2/positions?condition=
/trades, /activity, /value/v2/trades, /v2/activity, /v2/value
/holders, /oi, /live-volume/v2/holders, /v2/oi, /v2/live-volume
/traded/v2/user-stats
/v1/leaderboard/v2/leaderboard
CLOB /prices-history/v2/prices-history on the data host

What changes in your code: results move inside data; fields switch from camelCase (proxyWallet, conditionId, cashPnl) to snake_case (proxy_wallet, condition_id, unrealized_pnl); limit/offset paging (capped at 10,000 rows in v1) becomes cursors; and v2 returns 400 for the old market and offset parameters instead of ignoring them.

Data API, Gamma API, CLOB or a subgraph?

You wantUse
Positions, PnL, trade history, holders, leaderboardsData API (this page)
Find markets and events, token IDs, active markets sorted by liquidity or closing soonGamma API, e.g. /markets/keyset?closed=false&order=liquidity_num&ascending=false with end_date_max for markets ending soon
Live order book, prices, placing ordersCLOB API and the WebSocket
Raw on-chain history you index yourselfPolygon logs or an indexer; see on-chain data
Sources checked on 25 October 2026 (named, not linked): Polymarket docs pages Data API v2 overview, Migrate from Data API v1 to v2, Wallet Activity, Analytics, Rate Limits, the Data API v2 OpenAPI contract and the Predictions changelog (all under docs.polymarket.com and data-api.polymarket.com), the Gamma OpenAPI spec, and live calls to /v2/positions, /v2/trades, /v2/activity, /v2/value, /v2/leaderboard, /v2/status and the v1 /positions and /value routes.

Next: CLOB API (read the book, trade) · Gamma API (find markets) · Build a copy-trading bot.