REST API

Polymarket Analytics

Bounded Polymarket leaderboard, trader profile, positions, market summary, user categories, and platform-wide endpoints.

Weight: Fixed per request, depending on endpoint | Standard and Advanced tiers

These endpoints expose Polymarket-specific analytics that are not served through /v1/points. They are fixed-weight GET endpoints under /v1/polymarket/analytics/*, and they do not use the usual point-based weight formula. All examples use the standard public auth header:

Header
-H "X-Kiyotaka-Key: YOUR_API_KEY"

Common behavior

RuleDetails
Tier accessStandard and Advanced tiers
Weight modelFixed per endpoint
HTTP methodGET
Paginationlimit defaults to 20, offset defaults to 0
Pagination boundslimit <= 100, offset <= 10000
StreamingNot available on WebSocket

These endpoints are separate from /v1/points. They do not use type, exchange, interval, from, or period.

Top-level JSON fields are camelCase (traderProfiles, traderProfile, userPositions, marketSummary, userCategories). Nested Polymarket payload fields remain snake_case.

The JSON response can omit fields whose values are zero, empty, or unset. The response tables below list the available fields even when a specific response sample does not include every field. Long distribution arrays are shortened in the examples.

Composable PnL

Every endpoint accepts an optional repeated pnlComponents query parameter that controls how realized_pnl (and any field derived from it — sort order, min/max filters, win-rate aggregations, distribution percentiles) is computed.

Default

When pnlComponents is omitted, the trading_pnl subset is used:

trading_pnl = order_sell_pnl + order_buy_post_resolution_pnl + resolution_pnl + conversion_pnl

In our view this is the fairest way to capture real-trader behavior. It includes every market-exposure outcome (order fills, market resolutions, NegRisk conversions) and excludes inventory movement (merges, splits, transfers) which represent ledger bookkeeping rather than directional bets — those sources can dominate aggregator wallets and skew the headline number for wallets that aren't really trading.

What each component represents

ColumnSource eventWhat it tracks
order_sell_pnlorder_sellRealized PnL from sell orders. Mostly negative for losing trades, positive for winning trades that closed before resolution.
order_buy_post_resolution_pnlorder_buy_post_resolutionRealized PnL from buying tokens on already-resolved markets (immediately realized at the resolved price). Typically tiny — most flow is small post-res arbitrage.
merge_pnlmergeRealized PnL from merging YES+NO pairs back into USDC. Settlement signal: if this dominates total_realized_pnl, the wallet is more aggregator than trader.
split_post_resolution_pnlsplit_post_resolutionRealized PnL from splits on already-resolved markets (rare — economically pointless). Usually zero.
transfer_out_pnltransfer_outRealized PnL from sending tokens out. Always ≤ 0 (exit price = 0, captures cost-basis loss). For wallets that drain to other addresses (e.g. own cold wallet), large negative values are bookkeeping artifacts, not economic loss.
transfer_in_post_resolution_pnltransfer_in_post_resolutionRealized PnL from receiving tokens after the market resolved (immediately realized). Always ≥ 0 — receiver gets the resolved value at cost 0. Settlement signal for receive-and-redeem aggregators.
resolution_pnlresolutionRealized PnL when a market resolves while you hold positions. Typically dominates real-trader profiles — losing tokens go to 0, winners go to 1.
conversion_pnlconversionRealized PnL from NegRisk conversion events (Phase 1 NO exits at (N-1)/N + Phase 3 YES post-resolution arrivals). Net sign depends on whether NO cost basis was higher or lower than (N-1)/N.

Overriding the default

Repeat the pnlComponents parameter to compose a custom subset:

?pnlComponents=POLYMARKET_PNL_COMPONENT_ORDER_SELL&pnlComponents=POLYMARKET_PNL_COMPONENT_RESOLUTION

Enum valueMaps to column
POLYMARKET_PNL_COMPONENT_ORDER_SELLorder_sell_pnl
POLYMARKET_PNL_COMPONENT_ORDER_BUY_POST_RESOLUTIONorder_buy_post_resolution_pnl
POLYMARKET_PNL_COMPONENT_RESOLUTIONresolution_pnl
POLYMARKET_PNL_COMPONENT_CONVERSIONconversion_pnl
POLYMARKET_PNL_COMPONENT_MERGEmerge_pnl
POLYMARKET_PNL_COMPONENT_SPLIT_POST_RESOLUTIONsplit_post_resolution_pnl
POLYMARKET_PNL_COMPONENT_TRANSFER_OUTtransfer_out_pnl
POLYMARKET_PNL_COMPONENT_TRANSFER_IN_POST_RESOLUTIONtransfer_in_post_resolution_pnl

The pnl_by_source field on every response shows all eight sources independently of pnlComponents — it is informational, always populated with the full breakdown so consumers can see where each row's PnL came from.

Endpoint overview

EndpointWeightPurpose
/v1/polymarket/analytics/leaderboard60Browse trader leaderboard results with bounded filters and sorting
/v1/polymarket/analytics/trader-profile100Fetch a single trader profile for one wallet
/v1/polymarket/analytics/positions40Fetch bounded position rows by wallet, asset, or condition
/v1/polymarket/analytics/market-summary60Fetch a market summary for exactly one assetId or conditionId
/v1/polymarket/analytics/user-categories40Fetch a trader's category breakdown for one wallet
/v1/polymarket/analytics/platform-summary100Platform-wide aggregate statistics across every wallet
/v1/polymarket/analytics/platform-distribution100Banded or cumulative distribution of wallets by a chosen metric

When the target is a known market rather than a specific outcome token, prefer conditionId.

Leaderboard

GET/v1/polymarket/analytics/leaderboard

Returns a bounded list of trader profiles. By default it sorts by realized PnL descending.

Parameters

ParameterTypeRequiredDescription
limitint32NoNumber of rows to return. Default: 20. Max: 100.
offsetint32NoZero-based pagination offset. Default: 0. Max: 10000.
assetIdstringNoRestrict the leaderboard to one outcome token. Mutually exclusive with conditionId. Switches to the market-scoped path described below.
conditionIdstringNoRestrict the leaderboard to one market. Mutually exclusive with assetId. Switches to the market-scoped path described below.
roiPercentageint64NoMinimum realized ROI percentage. Not supported when assetId or conditionId is set.
minTotalTradeCountdoubleNoMinimum total position count.
maxTotalTradeCountdoubleNoMaximum total position count.
winRatedoubleNoMinimum win rate percentage.
avgPositionSizedoubleNoMinimum average position size.
totalVolumedoubleNoMinimum total traded size.
primaryCategorystringNoFilter to traders who have traded a category, for example Politics. Not supported when assetId or conditionId is set (redundant).
openPositionCountint64NoMinimum number of open positions.
timeSinceLastTradeint64NoMinimum seconds since the latest trade.
avgHoldingTimeint64NoMinimum average holding duration in seconds.
sortByenumNoREALIZED_PNL, ROI, WIN_COUNT, WIN_RATE, TOTAL_SIZE, TOTAL_POSITION_COUNT, or LAST_OPEN_TS. When the leaderboard is market-scoped (see below), ROI is not allowed.
sortDirectionenumNoSORT_DIRECTION_ASC or SORT_DIRECTION_DESC.
pnlComponentsenum, repeatedNoSee Composable PnL. Affects total_realized_pnl, ROI calculations, and REALIZED_PNL sort order.

Market-scoped leaderboard

When assetId or conditionId is set, the leaderboard is computed per-wallet within that market scope rather than read from the global trader roll-up. This changes both the accepted parameters and the meaning of some response fields.

RuleDetails
Mutual exclusivityOnly one of assetId, conditionId may be set.
Allowed sortByREALIZED_PNL, WIN_COUNT, WIN_RATE, TOTAL_SIZE, TOTAL_POSITION_COUNT, LAST_OPEN_TS. ROI and positions-level fields (REALIZED_SIZE, UNREALIZED_SIZE, AVG_PRICE) are rejected.
Rejected filtersroiPercentage, primaryCategory.
Unpopulated response fieldstotal_roi and total_unrealized_pnl are left at zero — ROI requires cost basis and unrealized PnL requires live outcome prices, neither of which the positions table exposes.
closed_position_count semanticsCounts positions with any realized activity (realized_size > 0) rather than fully closed positions, so that arbitrage rounds inside a still-open position are still counted.
win_rate_by_positions denominatorUses the same "positions with realized activity" population as closed_position_count above, keeping numerator and denominator drawn from the same set so arbitrage wins are credited.

Response fields

Each entry in traderProfiles is a PolymarketTraderProfile:

FieldTypeDescription
wallet_addressstringTrader wallet address
total_position_countint64Total number of tracked positions
open_position_countint64Number of currently open positions
closed_position_countint64Number of closed positions
latest_open_position_tsobjectLatest open position timestamp, with seconds and nanoseconds
total_sizedoubleTotal tracked position size
total_realized_pnldoubleTotal realized PnL
total_unrealized_pnldoubleTotal unrealized PnL
total_roidoubleTotal return on investment
win_rate_by_positionsdoubleWin rate by closed positions
largest_windoubleLargest realized win
largest_lossdoubleLargest realized loss
avg_holding_durationint64Average holding duration in seconds
total_open_pos_valuedoubleTotal value of open positions
total_closed_pos_valuedoubleTotal value of closed positions
total_cost_basisdoubleLifetime cost basis (sum of order_buy_cost + split_cost across all positions)
avg_open_investmentdoubleAverage capital deployed in open positions
total_order_buy_costdoubleLifetime spend on order-fill buys
total_split_costdoubleLifetime spend on split events
pnl_by_sourceobjectPer-event-type PnL breakdown across all 8 sources. See Pnl by source below.
event_countsobjectAggregate event counters: buys, sells, splits, merges, transfers (in + out), conversions (in + out)

PnL by source

The pnl_by_source object is shared across PolymarketTraderProfile, PolymarketUserPositions, PolymarketMarketSummary, and PolymarketTraderCategoryBreakdown. It exposes all eight per-event-type PnL columns regardless of pnlComponents:

FieldDescription
order_sellRealized PnL from selling order fills
order_buy_post_resolutionRealized PnL from buying after market resolution
resolutionRealized PnL credited at market resolution
conversionRealized PnL from token conversion events
mergeRealized PnL from outcome-token merge events
split_post_resolutionRealized PnL from split events post-resolution
transfer_outRealized PnL attributed to outbound transfers
transfer_in_post_resolutionRealized PnL attributed to inbound post-resolution transfers

Example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/leaderboard?limit=1" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "traderProfiles": [
    {
      "wallet_address": "0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab",
      "total_position_count": 1047,
      "closed_position_count": 1047,
      "total_size": 193273897.17371872,
      "total_realized_pnl": 94916520.2155992,
      "win_rate_by_positions": 80.70678127984718,
      "largest_win": 5740012.643231001,
      "largest_loss": -48.26,
      "avg_holding_duration": 3429946,
      "total_closed_pos_value": 193273897.17371872
    }
  ]
}

Trader Profile

GET/v1/polymarket/analytics/trader-profile

Returns a single trader profile for exactly one wallet.

Parameters

ParameterTypeRequiredDescription
userWalletstringYesWallet address, for example 0x...
pnlComponentsenum, repeatedNoSee Composable PnL. Affects total_realized_pnl and the ROI calculation.

Response

The response contains a single traderProfile object with the same shape as leaderboard rows, including pnl_by_source, event_counts, total_cost_basis, avg_open_investment, total_order_buy_cost, and total_split_cost.

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/trader-profile?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "traderProfile": {
    "wallet_address": "0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab",
    "total_position_count": 1047,
    "closed_position_count": 1047,
    "total_size": 193273897.17371872,
    "total_realized_pnl": 94916520.2155992,
    "win_rate_by_positions": 80.70678127984718,
    "largest_win": 5740012.643231001,
    "largest_loss": -48.26,
    "avg_holding_duration": 3429946,
    "total_closed_pos_value": 193273897.17371872
  }
}

Positions

GET/v1/polymarket/analytics/positions

Returns bounded position rows for one wallet, one asset, or one market condition.

Parameters

ParameterTypeRequiredDescription
userWalletstringNoWallet address. Can be used alone or together with one identifier.
assetIdstringNoOutcome token identifier. Mutually exclusive with conditionId.
conditionIdstringNoMarket condition identifier. Mutually exclusive with assetId.
limitint32NoNumber of rows to return. Default: 20. Max: 100.
offsetint32NoZero-based pagination offset. Default: 0. Max: 10000.
sortByenumNoLAST_OPEN_TS, REALIZED_PNL, REALIZED_SIZE, AVG_PRICE, or UNREALIZED_SIZE. Other sort fields belong to the leaderboard and are rejected here.
sortDirectionenumNoSORT_DIRECTION_ASC or SORT_DIRECTION_DESC. Defaults to descending. Closed positions (no latest_open_ts) sort last regardless of direction when sorting by LAST_OPEN_TS.
positionStatusenumNoOPEN_POSITIONS or CLOSED_POSITIONS. Filters by whether latest_open_ts is set.
openedBeforeint64NoUnix seconds. Keeps rows with latest_open_ts < openedBefore. Cannot be combined with positionStatus=CLOSED_POSITIONS.
openedAfterint64NoUnix seconds. Keeps rows with latest_open_ts > openedAfter. Must be < openedBefore when both are set. Cannot be combined with positionStatus=CLOSED_POSITIONS.
minRealizedPnldoubleNoMinimum realized_pnl. Must be <= maxRealizedPnl when both are set.
maxRealizedPnldoubleNoMaximum realized_pnl.
minRealizedSizedoubleNoMinimum realized_size. Must be <= maxRealizedSize when both are set.
maxRealizedSizedoubleNoMaximum realized_size.
minUnrealizedSizedoubleNoMinimum unrealized_size. Must be <= maxUnrealizedSize when both are set.
maxUnrealizedSizedoubleNoMaximum unrealized_size.
pnlComponentsenum, repeatedNoSee Composable PnL. Affects realized_pnl, the minRealizedPnl/maxRealizedPnl filters, and REALIZED_PNL sort order.

Valid request shapes

  • userWallet=<wallet>
  • userWallet=<wallet>&assetId=<asset_id>
  • userWallet=<wallet>&conditionId=<condition_id>
  • assetId=<asset_id>
  • conditionId=<condition_id> At least one of userWallet, assetId, or conditionId is required. assetId and conditionId cannot be set together.

Response fields

Each entry in userPositions is a PolymarketUserPositions row:

FieldTypeDescription
wallet_addressstringTrader wallet address
asset_idstringOutcome token identifier
unrealized_sizedoubleCurrently unrealized position size
realized_sizedoubleRealized position size
avg_pricedoubleAverage entry price
avg_exit_pricedoubleAverage exit price
realized_pnldoubleRealized PnL
resolved_pricedoubleFinal resolved price, when available
latest_open_tsint64Latest open timestamp
prev_hold_durationint64Previous holding duration in seconds
buy_countint32Number of buy events
sell_countint32Number of sell events
split_countint32Number of split events
merge_countint32Number of merge events
transfer_in_countint32Number of inbound transfer events
transfer_out_countint32Number of outbound transfer events
conversion_in_countint32Number of inbound conversion events
conversion_out_countint32Number of outbound conversion events
market_namestringMarket title
outcome_namestringOutcome label
categorystringMarket category
sub_categorystringMarket sub-category
condition_idstringMarket condition identifier
order_buy_costdoubleCost basis attributable to order-fill buys on this position
split_costdoubleCost basis attributable to split events on this position
pnl_by_sourceobjectPer-event-type PnL breakdown for this position. See Pnl by source.

Example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/positions?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab&limit=1" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "userPositions": [
    {
      "wallet_address": "0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab",
      "asset_id": "69984203794322070924779554468751071533998686576952069110752844084141678897886",
      "realized_size": 11555027.501624001,
      "avg_exit_price": 0.49675456353732356,
      "realized_pnl": 5740012.643231001,
      "resolved_price": 1,
      "prev_hold_duration": 14305671,
      "merge_count": 153,
      "transfer_in_count": 383,
      "transfer_out_count": 24,
      "market_name": "Which party will control the U.S. Senate after the 2022 election?",
      "outcome_name": "Democratic",
      "category": "Politics",
      "sub_category": "US Politics",
      "condition_id": "0xe0658c4beed2102c181b3987edff5edd578ad2952a6eb5fa8018925e5d7a48fd"
    }
  ]
}

Market Summary

GET/v1/polymarket/analytics/market-summary

Returns a market summary for exactly one assetId or one conditionId.

Parameters

ParameterTypeRequiredDescription
assetIdstringNoOutcome token identifier
conditionIdstringNoMarket condition identifier
pnlComponentsenum, repeatedNoSee Composable PnL. Affects realized_pnl_distribution, realized_pnl_min/max, and win_rate.

Exactly one of assetId or conditionId is required.

Response fields

The response contains a single marketSummary object:

FieldTypeDescription
event_idstringPolymarket event identifier
condition_idstring[]Condition IDs included in the summary
total_open_positionsint32Open position count
total_closed_positionsint32Closed position count
total_cost_basisdoubleTotal cost basis
total_sizedoubleTotal traded size
largest_open_positiondoubleLargest open position size
total_buy_countint32Total buy event count
total_sell_countint32Total sell event count
total_split_countint32Total split event count
total_merge_countint32Total merge event count
total_transfer_in_countint32Total inbound transfer event count
total_transfer_out_countint32Total outbound transfer event count
total_conversion_in_countint32Total inbound conversion event count
total_conversion_out_countint32Total outbound conversion event count
net_transfer_flowint32Net transfer flow count
net_conversion_flowint32Net conversion flow count
median_hold_durationdoubleMedian holding duration in seconds
mean_hold_durationdoubleMean holding duration in seconds
realized_pnl_mindoubleMinimum realized PnL
realized_pnl_maxdoubleMaximum realized PnL
realized_pnl_distributiondouble[]Realized PnL percentile values from p0 to p99
win_ratedoubleWin rate for the summarized market
avg_buy_countdoubleAverage buy event count
avg_sell_countdoubleAverage sell event count
avg_sizedoubleAverage position size
total_order_buy_costdoubleSum of order-fill buy cost across all positions in scope
total_split_costdoubleSum of split-event cost across all positions in scope
pnl_by_sourceobjectPer-event-type PnL breakdown aggregated across the market's positions. See Pnl by source.
outcome_pricingobject[]Per-outcome token pricing rows

Each row in outcome_pricing includes:

FieldTypeDescription
condition_idstringMarket condition identifier
token_idstringOutcome token identifier
outcome_namestringOutcome label
weighted_avg_entry_pricedoubleWeighted average entry price
weighted_avg_exit_pricedoubleWeighted average exit price
open_pos_avg_price_distributiondouble[]101 buckets; index i is the account count with average entry price in [i, i+1) cents
closed_pos_avg_exit_price_distributiondouble[]101 buckets; index i is the account count with average exit price in [i, i+1) cents

Example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/market-summary?assetId=69984203794322070924779554468751071533998686576952069110752844084141678897886" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "marketSummary": {
    "event_id": "3506",
    "condition_id": [
      "0xe0658c4beed2102c181b3987edff5edd578ad2952a6eb5fa8018925e5d7a48fd"
    ],
    "total_open_positions": 12,
    "total_closed_positions": 934,
    "total_cost_basis": 3287751.5362184998,
    "total_size": 13278317.319730995,
    "largest_open_position": 6517160.129311998,
    "total_split_count": 10516,
    "total_merge_count": 6370,
    "total_transfer_in_count": 10523,
    "total_transfer_out_count": 10523,
    "median_hold_duration": 19340026,
    "mean_hold_duration": 15813372.224219989,
    "realized_pnl_min": -7865106.637885602,
    "realized_pnl_max": 5740012.643231001,
    "realized_pnl_distribution": [
      -7865106.637885602,
      -0.00046407000000012324,
      0,
      74042.54808002156
    ],
    "win_rate": 0.5288259958071279,
    "avg_size": 48280.608293311605,
    "outcome_pricing": [
      {
        "condition_id": "0xe0658c4beed2102c181b3987edff5edd578ad2952a6eb5fa8018925e5d7a48fd",
        "token_id": "111299642775108135148113523472260651188510255643046337855221699185339755388694",
        "outcome_name": "Republican",
        "weighted_avg_entry_price": 0.000005283318038929714,
        "weighted_avg_exit_price": 0.1733132532287334,
        "open_pos_avg_price_distribution": [10, 0, 0, 3],
        "closed_pos_avg_exit_price_distribution": [872, 1, 2, 24]
      }
    ]
  }
}

User Categories

GET/v1/polymarket/analytics/user-categories

Returns a category breakdown for exactly one wallet.

Parameters

ParameterTypeRequiredDescription
userWalletstringYesWallet address, for example 0x...
pnlComponentsenum, repeatedNoSee Composable PnL. Affects realized_pnl per category.

Response fields

The response contains a single userCategories object:

FieldTypeDescription
wallet_addressstringTrader wallet address
category_breakdownobject[]Category-level breakdown rows

Each row in category_breakdown includes:

FieldTypeDescription
market_categorystringTop-level category name
market_sub_categorystringSub-category name
countint64Number of positions in that category
realized_sizedoubleRealized traded size
unrealized_sizedoubleUnrealized size
realized_pnldoubleRealized PnL for that category
pnl_by_sourceobjectPer-event-type PnL breakdown for this category. See Pnl by source.

Example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/user-categories?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "userCategories": {
    "wallet_address": "0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab",
    "category_breakdown": [
      {
        "market_category": "Politics",
        "market_sub_category": "US Politics",
        "count": 248,
        "realized_size": 114739709.61980493,
        "realized_pnl": 56646616.73381202
      }
    ]
  }
}

Platform Summary

GET/v1/polymarket/analytics/platform-summary

Returns a single one-row aggregate across every wallet in the trader summary table. Useful for headline platform-level statistics: total accounts, net PnL, lifetime traded volume, activity histogram, and PnL composition.

Parameters

ParameterTypeRequiredDescription
pnlComponentsenum, repeatedNoSee Composable PnL. Affects every PnL-derived field in the response.

Response fields

The response contains a single platformSummary object:

FieldTypeDescription
accounts_totalint64Total number of wallets in the trader summary
accounts_activeint64Wallets with total_position_count > 0
accounts_profitableint64Wallets whose realized_pnl > 0
accounts_losingint64Wallets whose realized_pnl < 0
accounts_flatint64Wallets whose realized_pnl = 0
total_winningsdoubleSum of positive realized_pnl across all wallets
total_lossesdoubleSum of negative realized_pnl across all wallets
net_pnldoubleSum of realized_pnl across all wallets
lifetime_buy_notional_inc_splitsdoubleSum of total_cost_basis across all wallets
lifetime_order_buy_notionaldoubleSum of order_buy_cost across all wallets
pnl_by_sourceobjectPlatform-level PnL composition. See Pnl by source.
activity_histogramobjectWallet count by position-count tier (see below)
median_pnldoublep50 of realized_pnl across the population
p90_pnldoublep90 of realized_pnl
p99_pnldoublep99 of realized_pnl
max_pnldoubleLargest single-wallet realized_pnl
min_pnldoubleSmallest (most negative) single-wallet realized_pnl
event_countsobjectAggregate event counters across the population (see below)

The activity_histogram object segments wallets by total position count:

FieldBucket
position_count_1Wallets with exactly 1 position
position_count_2_to_52..5 positions
position_count_6_to_206..20 positions
position_count_21_to_10021..100 positions
position_count_over_100More than 100 positions

The event_counts object reports platform-wide event totals. transfers and conversions combine inbound and outbound counts:

FieldDescription
buysTotal buy event count
sellsTotal sell event count
splitsTotal split event count
mergesTotal merge event count
transfersTotal inbound + outbound transfer event count
conversionsTotal inbound + outbound conversion event count

Example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-summary" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "platformSummary": {
    "accounts_total": 2739335,
    "accounts_active": 2739335,
    "accounts_profitable": 823831,
    "accounts_losing": 1837378,
    "accounts_flat": 78126,
    "total_winnings": 1361047633.76,
    "total_losses": -1251703742.46,
    "net_pnl": 109343891.31,
    "lifetime_buy_notional_inc_splits": 52550871389.34,
    "lifetime_order_buy_notional": 46912201989.79,
    "pnl_by_source": {
      "order_sell": 909073054.48,
      "resolution": -534585069.09,
      "conversion": -265420097.80,
      "merge": 571684457.36
    },
    "activity_histogram": {
      "position_count_1": 347111,
      "position_count_2_to_5": 592929,
      "position_count_6_to_20": 854469,
      "position_count_21_to_100": 706366,
      "position_count_over_100": 238460
    },
    "median_pnl": -2.29,
    "p90_pnl": 51.69,
    "p99_pnl": 3764.29,
    "max_pnl": 22045623.06,
    "min_pnl": -10050886.06,
    "event_counts": {
      "buys": 1007876643,
      "sells": 240034517,
      "splits": 22792454,
      "merges": 28080874,
      "transfers": 24089475,
      "conversions": 48485205
    }
  }
}

Platform Distribution

GET/v1/polymarket/analytics/platform-distribution

Returns the distribution of wallets across bands defined by a chosen ranking dimension. Two output shapes are available: banded (default) returns one row per band with per-band aggregates, and cumulative returns one row per band edge with running Lorenz-curve totals.

Parameters

ParameterTypeRequiredDescription
distributionRankByenumYesThe dimension wallets are ranked on. See enum table below.
distributionBandPresetenumYesPOLYMARKET_DISTRIBUTION_BAND_PRESET_DECILES (10 even bands) or POLYMARKET_DISTRIBUTION_BAND_PRESET_SYMMETRIC_PERCENTILE (14 bands with thinner top/bottom tails — 0.1%, 1%, decile interior, 99%, 99.9%).
distributionCumulativeboolNoWhen true, the response shape switches from banded aggregates to running cumulative points.
distributionMinPositionsint64NoActivity gate. Wallets with fewer than this many positions are excluded. Defaults to 1. Must be >= 0. When ranking by WIN_RATE, also gates wallets by closed_position_count.
pnlComponentsenum, repeatedNoSee Composable PnL. Affects ranking when rankBy=TRADING_PNL and PnL-related per-band metrics.

Ranking dimensions

distributionRankByUnderlying expression
POLYMARKET_DISTRIBUTION_RANK_BY_TRADING_PNLThe composable PnL sum (see Composable PnL)
POLYMARKET_DISTRIBUTION_RANK_BY_TRADE_COUNTbuy_count + sell_count
POLYMARKET_DISTRIBUTION_RANK_BY_POSITION_COUNTtotal_position_count
POLYMARKET_DISTRIBUTION_RANK_BY_AVG_OPEN_INVESTMENTavg_open_investment
POLYMARKET_DISTRIBUTION_RANK_BY_AVG_HOLDING_DURATIONavg_holding_duration
POLYMARKET_DISTRIBUTION_RANK_BY_WIN_RATEwin_count / closed_position_count
POLYMARKET_DISTRIBUTION_RANK_BY_TOTAL_SIZEtotal_size
POLYMARKET_DISTRIBUTION_RANK_BY_TOTAL_COST_BASIStotal_cost_basis

Validation rules

RuleBehavior
distributionRankBy missing or UNKNOWN400
distributionBandPreset missing or UNKNOWN400
distributionMinPositions < 0400
distributionCumulative=true with a non-additive rankBy400. Cumulative mode is only supported for additive rank dimensions: TRADING_PNL, TRADE_COUNT, POSITION_COUNT, TOTAL_SIZE, TOTAL_COST_BASIS. Ratio/average dimensions (WIN_RATE, AVG_HOLDING_DURATION, AVG_OPEN_INVESTMENT) cannot be summed across wallets and are rejected.

Banded mode response

When distributionCumulative is unset or false, the response contains a platformDistribution.distribution_bands array with one entry per non-empty band:

FieldTypeDescription
band_idint321-indexed band position, ordered top-to-bottom by ranking dimension
band_labelstringDescriptive band name (e.g. "top_0.1pct", "10-20pct", "bottom_10pct")
account_countint64Wallets in this band
pct_profitabledoublePercentage of wallets in this band whose trading_pnl > 0
avg_pnldoubleAverage trading_pnl in the band
total_pnldoubleSum of trading_pnl in the band
median_pnldoubleMedian trading_pnl in the band
rank_value_mindoubleMinimum value of the ranking dimension within the band
rank_value_maxdoubleMaximum value of the ranking dimension within the band
median_rank_valuedoubleMedian value of the ranking dimension within the band
avg_trade_countdoubleAverage buy_count + sell_count in the band
avg_position_countdoubleAverage total_position_count in the band
avg_holding_durationdoubleAverage non-zero holding duration in the band
win_ratedoubleSUM(win_count) / SUM(closed_position_count) within the band
pnl_by_sourceobjectPer-event-type PnL breakdown for this band. See Pnl by source.

Empty bands are omitted from the array.

Cumulative mode response

When distributionCumulative=true, the response contains a platformDistribution.distribution_cumulative array with one entry per band edge (Lorenz curve points):

FieldTypeDescription
pct_from_topdoubleCumulative cutoff: this row aggregates the top pct_from_top fraction of wallets by the chosen rank dimension
cumulative_metricdoubleSigned sum of the rank dimension contributed by everyone in the cutoff
cumulative_share_winningsdoubleFraction of all winners' positive contribution captured in the cutoff. Bounded in [0, 1]. For non-signed rank dimensions, this is the canonical "share of total" metric.
cumulative_share_lossesdoubleFraction of all losers' negative contribution captured in the cutoff. Bounded in [0, 1]. Always 0 for non-signed rank dimensions.

For the journalist-style framing "top X% of traders captured Y% of platform PnL", read cumulative_share_winnings at the top end of the curve and cumulative_share_losses at the bottom end.

Banded example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-distribution?distributionRankBy=POLYMARKET_DISTRIBUTION_RANK_BY_TRADE_COUNT&distributionBandPreset=POLYMARKET_DISTRIBUTION_BAND_PRESET_DECILES" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "platformDistribution": {
    "distribution_bands": [
      {
        "band_id": 1,
        "band_label": "top_10pct",
        "account_count": 274583,
        "pct_profitable": 28.93,
        "avg_pnl": 460.81,
        "total_pnl": 126530090.50,
        "median_pnl": -33.03,
        "rank_value_min": 204,
        "rank_value_max": 12921374,
        "avg_trade_count": 4243.36,
        "avg_position_count": 657.17,
        "win_rate": 0.52,
        "pnl_by_source": {
          "order_sell": 848837021.26,
          "resolution": -461390095.32
        }
      }
    ]
  }
}

Cumulative example

cURL
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-distribution?distributionRankBy=POLYMARKET_DISTRIBUTION_RANK_BY_TRADING_PNL&distributionBandPreset=POLYMARKET_DISTRIBUTION_BAND_PRESET_DECILES&distributionCumulative=true" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"
JSON
{
  "platformDistribution": {
    "distribution_cumulative": [
      {
        "pct_from_top": 0.1,
        "cumulative_metric": 1356055105.34,
        "cumulative_share_winnings": 0.9963
      },
      {
        "pct_from_top": 0.5,
        "cumulative_metric": 1360747391.18,
        "cumulative_share_winnings": 1,
        "cumulative_share_losses": 0.000269
      },
      {
        "pct_from_top": 1,
        "cumulative_metric": 109381185.36,
        "cumulative_share_winnings": 1,
        "cumulative_share_losses": 1
      }
    ]
  }
}

Reading this curve: the top 10% by trading_pnl captured 99.6% of all platform winnings, and the bottom 10% (going from pct_from_top=0.9 to 1.0) captured roughly 96% of all platform losses.


Typical workflows

Common starting points fall into three categories:

  • inspect a trader
  • inspect a market
  • inspect platform-wide statistics Choose the workflow that matches the task. Not every endpoint needs to be called in sequence.

Start from a trader

Use this flow to discover a wallet first, then inspect that trader's profile, category mix, and positions.

  1. Call /leaderboard with a small limit to get a wallet.
  2. Extract traderProfiles[0].wallet_address.
  3. Reuse that wallet with /trader-profile, /user-categories, or /positions.
  4. For market-level context on one returned position, extract condition_id from /positions and call /market-summary.
Bash
WALLET=$(curl -s "https://api.kiyotaka.ai/v1/polymarket/analytics/leaderboard?limit=1" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY" | jq -r '.traderProfiles[0].wallet_address')


curl "https://api.kiyotaka.ai/v1/polymarket/analytics/trader-profile?userWallet=\${WALLET}" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"


curl "https://api.kiyotaka.ai/v1/polymarket/analytics/user-categories?userWallet=\${WALLET}" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"


CONDITION_ID=$(curl -s "https://api.kiyotaka.ai/v1/polymarket/analytics/positions?userWallet=\${WALLET}&limit=1" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY" | jq -r '.userPositions[0].condition_id')


curl "https://api.kiyotaka.ai/v1/polymarket/analytics/market-summary?conditionId=\${CONDITION_ID}" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"

Start from a market

Use this flow when the market is already known and a conditionId is available.

  1. Start with a conditionId.
  2. Call /market-summary with that conditionId.
  3. Optionally call /positions?conditionId=... to inspect position rows for that market. The example below uses the same conditionId shown in the /positions example above, so the commands can be run directly.
Bash
CONDITION_ID="0xe0658c4beed2102c181b3987edff5edd578ad2952a6eb5fa8018925e5d7a48fd"


curl "https://api.kiyotaka.ai/v1/polymarket/analytics/market-summary?conditionId=\${CONDITION_ID}" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"


curl "https://api.kiyotaka.ai/v1/polymarket/analytics/positions?conditionId=\${CONDITION_ID}&limit=5" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"

These examples use jq to extract identifiers from JSON. Without jq, extract traderProfiles[0].wallet_address or userPositions[0].condition_id from the responses and reuse those values manually.

Start from platform-wide stats

Use this flow when the question is about the overall shape of trader activity, PnL concentration, or platform-level totals — for example, journalistic claims like "top 0.1% of traders captured X% of platform PnL".

  1. Call /platform-summary for the headline numbers (account counts, totals, percentiles, PnL composition, activity histogram).
  2. Call /platform-distribution with a chosen distributionRankBy to see the per-band breakdown — average trade count, win rate, PnL composition per cohort.
  3. For concentration claims, repeat the call with distributionCumulative=true to read the Lorenz curve directly via cumulative_share_winnings and cumulative_share_losses.
Bash
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-summary" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"


# Banded view of the trade-count distribution
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-distribution?distributionRankBy=POLYMARKET_DISTRIBUTION_RANK_BY_TRADE_COUNT&distributionBandPreset=POLYMARKET_DISTRIBUTION_BAND_PRESET_SYMMETRIC_PERCENTILE" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"


# Cumulative Lorenz curve for the PnL concentration story
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-distribution?distributionRankBy=POLYMARKET_DISTRIBUTION_RANK_BY_TRADING_PNL&distributionBandPreset=POLYMARKET_DISTRIBUTION_BAND_PRESET_DECILES&distributionCumulative=true" \\
  -H "X-Kiyotaka-Key: YOUR_API_KEY"

Monitor weight consumption with GET /v1/usage, and see the Rate Limits page for the response headers and quota model.