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:
-H "X-Kiyotaka-Key: YOUR_API_KEY"
Common behavior
| Rule | Details |
|---|---|
| Tier access | Standard and Advanced tiers |
| Weight model | Fixed per endpoint |
| HTTP method | GET |
| Pagination | limit defaults to 20, offset defaults to 0 |
| Pagination bounds | limit <= 100, offset <= 10000 |
| Streaming | Not 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
| Column | Source event | What it tracks |
|---|---|---|
order_sell_pnl | order_sell | Realized PnL from sell orders. Mostly negative for losing trades, positive for winning trades that closed before resolution. |
order_buy_post_resolution_pnl | order_buy_post_resolution | Realized PnL from buying tokens on already-resolved markets (immediately realized at the resolved price). Typically tiny — most flow is small post-res arbitrage. |
merge_pnl | merge | Realized 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_pnl | split_post_resolution | Realized PnL from splits on already-resolved markets (rare — economically pointless). Usually zero. |
transfer_out_pnl | transfer_out | Realized 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_pnl | transfer_in_post_resolution | Realized 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_pnl | resolution | Realized PnL when a market resolves while you hold positions. Typically dominates real-trader profiles — losing tokens go to 0, winners go to 1. |
conversion_pnl | conversion | Realized 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 value | Maps to column |
|---|---|
POLYMARKET_PNL_COMPONENT_ORDER_SELL | order_sell_pnl |
POLYMARKET_PNL_COMPONENT_ORDER_BUY_POST_RESOLUTION | order_buy_post_resolution_pnl |
POLYMARKET_PNL_COMPONENT_RESOLUTION | resolution_pnl |
POLYMARKET_PNL_COMPONENT_CONVERSION | conversion_pnl |
POLYMARKET_PNL_COMPONENT_MERGE | merge_pnl |
POLYMARKET_PNL_COMPONENT_SPLIT_POST_RESOLUTION | split_post_resolution_pnl |
POLYMARKET_PNL_COMPONENT_TRANSFER_OUT | transfer_out_pnl |
POLYMARKET_PNL_COMPONENT_TRANSFER_IN_POST_RESOLUTION | transfer_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
| Endpoint | Weight | Purpose |
|---|---|---|
/v1/polymarket/analytics/leaderboard | 60 | Browse trader leaderboard results with bounded filters and sorting |
/v1/polymarket/analytics/trader-profile | 100 | Fetch a single trader profile for one wallet |
/v1/polymarket/analytics/positions | 40 | Fetch bounded position rows by wallet, asset, or condition |
/v1/polymarket/analytics/market-summary | 60 | Fetch a market summary for exactly one assetId or conditionId |
/v1/polymarket/analytics/user-categories | 40 | Fetch a trader's category breakdown for one wallet |
/v1/polymarket/analytics/platform-summary | 100 | Platform-wide aggregate statistics across every wallet |
/v1/polymarket/analytics/platform-distribution | 100 | Banded 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
Returns a bounded list of trader profiles. By default it sorts by realized PnL descending.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | int32 | No | Number of rows to return. Default: 20. Max: 100. |
offset | int32 | No | Zero-based pagination offset. Default: 0. Max: 10000. |
assetId | string | No | Restrict the leaderboard to one outcome token. Mutually exclusive with conditionId. Switches to the market-scoped path described below. |
conditionId | string | No | Restrict the leaderboard to one market. Mutually exclusive with assetId. Switches to the market-scoped path described below. |
roiPercentage | int64 | No | Minimum realized ROI percentage. Not supported when assetId or conditionId is set. |
minTotalTradeCount | double | No | Minimum total position count. |
maxTotalTradeCount | double | No | Maximum total position count. |
winRate | double | No | Minimum win rate percentage. |
avgPositionSize | double | No | Minimum average position size. |
totalVolume | double | No | Minimum total traded size. |
primaryCategory | string | No | Filter to traders who have traded a category, for example Politics. Not supported when assetId or conditionId is set (redundant). |
openPositionCount | int64 | No | Minimum number of open positions. |
timeSinceLastTrade | int64 | No | Minimum seconds since the latest trade. |
avgHoldingTime | int64 | No | Minimum average holding duration in seconds. |
sortBy | enum | No | REALIZED_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. |
sortDirection | enum | No | SORT_DIRECTION_ASC or SORT_DIRECTION_DESC. |
pnlComponents | enum, repeated | No | See 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.
| Rule | Details |
|---|---|
| Mutual exclusivity | Only one of assetId, conditionId may be set. |
Allowed sortBy | REALIZED_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 filters | roiPercentage, primaryCategory. |
| Unpopulated response fields | total_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 semantics | Counts 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 denominator | Uses 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:
| Field | Type | Description |
|---|---|---|
wallet_address | string | Trader wallet address |
total_position_count | int64 | Total number of tracked positions |
open_position_count | int64 | Number of currently open positions |
closed_position_count | int64 | Number of closed positions |
latest_open_position_ts | object | Latest open position timestamp, with seconds and nanoseconds |
total_size | double | Total tracked position size |
total_realized_pnl | double | Total realized PnL |
total_unrealized_pnl | double | Total unrealized PnL |
total_roi | double | Total return on investment |
win_rate_by_positions | double | Win rate by closed positions |
largest_win | double | Largest realized win |
largest_loss | double | Largest realized loss |
avg_holding_duration | int64 | Average holding duration in seconds |
total_open_pos_value | double | Total value of open positions |
total_closed_pos_value | double | Total value of closed positions |
total_cost_basis | double | Lifetime cost basis (sum of order_buy_cost + split_cost across all positions) |
avg_open_investment | double | Average capital deployed in open positions |
total_order_buy_cost | double | Lifetime spend on order-fill buys |
total_split_cost | double | Lifetime spend on split events |
pnl_by_source | object | Per-event-type PnL breakdown across all 8 sources. See Pnl by source below. |
event_counts | object | Aggregate 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:
| Field | Description |
|---|---|
order_sell | Realized PnL from selling order fills |
order_buy_post_resolution | Realized PnL from buying after market resolution |
resolution | Realized PnL credited at market resolution |
conversion | Realized PnL from token conversion events |
merge | Realized PnL from outcome-token merge events |
split_post_resolution | Realized PnL from split events post-resolution |
transfer_out | Realized PnL attributed to outbound transfers |
transfer_in_post_resolution | Realized PnL attributed to inbound post-resolution transfers |
Example
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/leaderboard?limit=1" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
Returns a single trader profile for exactly one wallet.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userWallet | string | Yes | Wallet address, for example 0x... |
pnlComponents | enum, repeated | No | See 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 "https://api.kiyotaka.ai/v1/polymarket/analytics/trader-profile?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
Returns bounded position rows for one wallet, one asset, or one market condition.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userWallet | string | No | Wallet address. Can be used alone or together with one identifier. |
assetId | string | No | Outcome token identifier. Mutually exclusive with conditionId. |
conditionId | string | No | Market condition identifier. Mutually exclusive with assetId. |
limit | int32 | No | Number of rows to return. Default: 20. Max: 100. |
offset | int32 | No | Zero-based pagination offset. Default: 0. Max: 10000. |
sortBy | enum | No | LAST_OPEN_TS, REALIZED_PNL, REALIZED_SIZE, AVG_PRICE, or UNREALIZED_SIZE. Other sort fields belong to the leaderboard and are rejected here. |
sortDirection | enum | No | SORT_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. |
positionStatus | enum | No | OPEN_POSITIONS or CLOSED_POSITIONS. Filters by whether latest_open_ts is set. |
openedBefore | int64 | No | Unix seconds. Keeps rows with latest_open_ts < openedBefore. Cannot be combined with positionStatus=CLOSED_POSITIONS. |
openedAfter | int64 | No | Unix seconds. Keeps rows with latest_open_ts > openedAfter. Must be < openedBefore when both are set. Cannot be combined with positionStatus=CLOSED_POSITIONS. |
minRealizedPnl | double | No | Minimum realized_pnl. Must be <= maxRealizedPnl when both are set. |
maxRealizedPnl | double | No | Maximum realized_pnl. |
minRealizedSize | double | No | Minimum realized_size. Must be <= maxRealizedSize when both are set. |
maxRealizedSize | double | No | Maximum realized_size. |
minUnrealizedSize | double | No | Minimum unrealized_size. Must be <= maxUnrealizedSize when both are set. |
maxUnrealizedSize | double | No | Maximum unrealized_size. |
pnlComponents | enum, repeated | No | See 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 ofuserWallet,assetId, orconditionIdis required.assetIdandconditionIdcannot be set together.
Response fields
Each entry in userPositions is a PolymarketUserPositions row:
| Field | Type | Description |
|---|---|---|
wallet_address | string | Trader wallet address |
asset_id | string | Outcome token identifier |
unrealized_size | double | Currently unrealized position size |
realized_size | double | Realized position size |
avg_price | double | Average entry price |
avg_exit_price | double | Average exit price |
realized_pnl | double | Realized PnL |
resolved_price | double | Final resolved price, when available |
latest_open_ts | int64 | Latest open timestamp |
prev_hold_duration | int64 | Previous holding duration in seconds |
buy_count | int32 | Number of buy events |
sell_count | int32 | Number of sell events |
split_count | int32 | Number of split events |
merge_count | int32 | Number of merge events |
transfer_in_count | int32 | Number of inbound transfer events |
transfer_out_count | int32 | Number of outbound transfer events |
conversion_in_count | int32 | Number of inbound conversion events |
conversion_out_count | int32 | Number of outbound conversion events |
market_name | string | Market title |
outcome_name | string | Outcome label |
category | string | Market category |
sub_category | string | Market sub-category |
condition_id | string | Market condition identifier |
order_buy_cost | double | Cost basis attributable to order-fill buys on this position |
split_cost | double | Cost basis attributable to split events on this position |
pnl_by_source | object | Per-event-type PnL breakdown for this position. See Pnl by source. |
Example
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/positions?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab&limit=1" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
Returns a market summary for exactly one assetId or one conditionId.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
assetId | string | No | Outcome token identifier |
conditionId | string | No | Market condition identifier |
pnlComponents | enum, repeated | No | See 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:
| Field | Type | Description |
|---|---|---|
event_id | string | Polymarket event identifier |
condition_id | string[] | Condition IDs included in the summary |
total_open_positions | int32 | Open position count |
total_closed_positions | int32 | Closed position count |
total_cost_basis | double | Total cost basis |
total_size | double | Total traded size |
largest_open_position | double | Largest open position size |
total_buy_count | int32 | Total buy event count |
total_sell_count | int32 | Total sell event count |
total_split_count | int32 | Total split event count |
total_merge_count | int32 | Total merge event count |
total_transfer_in_count | int32 | Total inbound transfer event count |
total_transfer_out_count | int32 | Total outbound transfer event count |
total_conversion_in_count | int32 | Total inbound conversion event count |
total_conversion_out_count | int32 | Total outbound conversion event count |
net_transfer_flow | int32 | Net transfer flow count |
net_conversion_flow | int32 | Net conversion flow count |
median_hold_duration | double | Median holding duration in seconds |
mean_hold_duration | double | Mean holding duration in seconds |
realized_pnl_min | double | Minimum realized PnL |
realized_pnl_max | double | Maximum realized PnL |
realized_pnl_distribution | double[] | Realized PnL percentile values from p0 to p99 |
win_rate | double | Win rate for the summarized market |
avg_buy_count | double | Average buy event count |
avg_sell_count | double | Average sell event count |
avg_size | double | Average position size |
total_order_buy_cost | double | Sum of order-fill buy cost across all positions in scope |
total_split_cost | double | Sum of split-event cost across all positions in scope |
pnl_by_source | object | Per-event-type PnL breakdown aggregated across the market's positions. See Pnl by source. |
outcome_pricing | object[] | Per-outcome token pricing rows |
Each row in outcome_pricing includes:
| Field | Type | Description |
|---|---|---|
condition_id | string | Market condition identifier |
token_id | string | Outcome token identifier |
outcome_name | string | Outcome label |
weighted_avg_entry_price | double | Weighted average entry price |
weighted_avg_exit_price | double | Weighted average exit price |
open_pos_avg_price_distribution | double[] | 101 buckets; index i is the account count with average entry price in [i, i+1) cents |
closed_pos_avg_exit_price_distribution | double[] | 101 buckets; index i is the account count with average exit price in [i, i+1) cents |
Example
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/market-summary?assetId=69984203794322070924779554468751071533998686576952069110752844084141678897886" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
Returns a category breakdown for exactly one wallet.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userWallet | string | Yes | Wallet address, for example 0x... |
pnlComponents | enum, repeated | No | See Composable PnL. Affects realized_pnl per category. |
Response fields
The response contains a single userCategories object:
| Field | Type | Description |
|---|---|---|
wallet_address | string | Trader wallet address |
category_breakdown | object[] | Category-level breakdown rows |
Each row in category_breakdown includes:
| Field | Type | Description |
|---|---|---|
market_category | string | Top-level category name |
market_sub_category | string | Sub-category name |
count | int64 | Number of positions in that category |
realized_size | double | Realized traded size |
unrealized_size | double | Unrealized size |
realized_pnl | double | Realized PnL for that category |
pnl_by_source | object | Per-event-type PnL breakdown for this category. See Pnl by source. |
Example
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/user-categories?userWallet=0xf1302aafc43aa3a69bcd8058fc7a0259dac246ab" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
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
| Parameter | Type | Required | Description |
|---|---|---|---|
pnlComponents | enum, repeated | No | See Composable PnL. Affects every PnL-derived field in the response. |
Response fields
The response contains a single platformSummary object:
| Field | Type | Description |
|---|---|---|
accounts_total | int64 | Total number of wallets in the trader summary |
accounts_active | int64 | Wallets with total_position_count > 0 |
accounts_profitable | int64 | Wallets whose realized_pnl > 0 |
accounts_losing | int64 | Wallets whose realized_pnl < 0 |
accounts_flat | int64 | Wallets whose realized_pnl = 0 |
total_winnings | double | Sum of positive realized_pnl across all wallets |
total_losses | double | Sum of negative realized_pnl across all wallets |
net_pnl | double | Sum of realized_pnl across all wallets |
lifetime_buy_notional_inc_splits | double | Sum of total_cost_basis across all wallets |
lifetime_order_buy_notional | double | Sum of order_buy_cost across all wallets |
pnl_by_source | object | Platform-level PnL composition. See Pnl by source. |
activity_histogram | object | Wallet count by position-count tier (see below) |
median_pnl | double | p50 of realized_pnl across the population |
p90_pnl | double | p90 of realized_pnl |
p99_pnl | double | p99 of realized_pnl |
max_pnl | double | Largest single-wallet realized_pnl |
min_pnl | double | Smallest (most negative) single-wallet realized_pnl |
event_counts | object | Aggregate event counters across the population (see below) |
The activity_histogram object segments wallets by total position count:
| Field | Bucket |
|---|---|
position_count_1 | Wallets with exactly 1 position |
position_count_2_to_5 | 2..5 positions |
position_count_6_to_20 | 6..20 positions |
position_count_21_to_100 | 21..100 positions |
position_count_over_100 | More than 100 positions |
The event_counts object reports platform-wide event totals. transfers and conversions combine inbound and outbound counts:
| Field | Description |
|---|---|
buys | Total buy event count |
sells | Total sell event count |
splits | Total split event count |
merges | Total merge event count |
transfers | Total inbound + outbound transfer event count |
conversions | Total inbound + outbound conversion event count |
Example
curl "https://api.kiyotaka.ai/v1/polymarket/analytics/platform-summary" \\ -H "X-Kiyotaka-Key: YOUR_API_KEY"
{
"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
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
| Parameter | Type | Required | Description |
|---|---|---|---|
distributionRankBy | enum | Yes | The dimension wallets are ranked on. See enum table below. |
distributionBandPreset | enum | Yes | POLYMARKET_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%). |
distributionCumulative | bool | No | When true, the response shape switches from banded aggregates to running cumulative points. |
distributionMinPositions | int64 | No | Activity 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. |
pnlComponents | enum, repeated | No | See Composable PnL. Affects ranking when rankBy=TRADING_PNL and PnL-related per-band metrics. |
Ranking dimensions
distributionRankBy | Underlying expression |
|---|---|
POLYMARKET_DISTRIBUTION_RANK_BY_TRADING_PNL | The composable PnL sum (see Composable PnL) |
POLYMARKET_DISTRIBUTION_RANK_BY_TRADE_COUNT | buy_count + sell_count |
POLYMARKET_DISTRIBUTION_RANK_BY_POSITION_COUNT | total_position_count |
POLYMARKET_DISTRIBUTION_RANK_BY_AVG_OPEN_INVESTMENT | avg_open_investment |
POLYMARKET_DISTRIBUTION_RANK_BY_AVG_HOLDING_DURATION | avg_holding_duration |
POLYMARKET_DISTRIBUTION_RANK_BY_WIN_RATE | win_count / closed_position_count |
POLYMARKET_DISTRIBUTION_RANK_BY_TOTAL_SIZE | total_size |
POLYMARKET_DISTRIBUTION_RANK_BY_TOTAL_COST_BASIS | total_cost_basis |
Validation rules
| Rule | Behavior |
|---|---|
distributionRankBy missing or UNKNOWN | 400 |
distributionBandPreset missing or UNKNOWN | 400 |
distributionMinPositions < 0 | 400 |
distributionCumulative=true with a non-additive rankBy | 400. 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:
| Field | Type | Description |
|---|---|---|
band_id | int32 | 1-indexed band position, ordered top-to-bottom by ranking dimension |
band_label | string | Descriptive band name (e.g. "top_0.1pct", "10-20pct", "bottom_10pct") |
account_count | int64 | Wallets in this band |
pct_profitable | double | Percentage of wallets in this band whose trading_pnl > 0 |
avg_pnl | double | Average trading_pnl in the band |
total_pnl | double | Sum of trading_pnl in the band |
median_pnl | double | Median trading_pnl in the band |
rank_value_min | double | Minimum value of the ranking dimension within the band |
rank_value_max | double | Maximum value of the ranking dimension within the band |
median_rank_value | double | Median value of the ranking dimension within the band |
avg_trade_count | double | Average buy_count + sell_count in the band |
avg_position_count | double | Average total_position_count in the band |
avg_holding_duration | double | Average non-zero holding duration in the band |
win_rate | double | SUM(win_count) / SUM(closed_position_count) within the band |
pnl_by_source | object | Per-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):
| Field | Type | Description |
|---|---|---|
pct_from_top | double | Cumulative cutoff: this row aggregates the top pct_from_top fraction of wallets by the chosen rank dimension |
cumulative_metric | double | Signed sum of the rank dimension contributed by everyone in the cutoff |
cumulative_share_winnings | double | Fraction 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_losses | double | Fraction 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 "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"
{
"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 "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"
{
"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.
- Call
/leaderboardwith a smalllimitto get a wallet. - Extract
traderProfiles[0].wallet_address. - Reuse that wallet with
/trader-profile,/user-categories, or/positions. - For market-level context on one returned position, extract
condition_idfrom/positionsand call/market-summary.
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.
- Start with a
conditionId. - Call
/market-summarywith thatconditionId. - Optionally call
/positions?conditionId=...to inspect position rows for that market. The example below uses the sameconditionIdshown in the/positionsexample above, so the commands can be run directly.
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".
- Call
/platform-summaryfor the headline numbers (account counts, totals, percentiles, PnL composition, activity histogram). - Call
/platform-distributionwith a chosendistributionRankByto see the per-band breakdown — average trade count, win rate, PnL composition per cohort. - For concentration claims, repeat the call with
distributionCumulative=trueto read the Lorenz curve directly viacumulative_share_winningsandcumulative_share_losses.
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.