@0xinsider/sdk 0.31.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.d.ts CHANGED
@@ -3,7 +3,8 @@ export type AccountIdentity = {
3
3
  data: {
4
4
  user_id: number;
5
5
  credential_id: number;
6
- credential_kind: "api_key" | "oauth_grant";
6
+ /** The kind of credential that made the request: api_key is a full-access developer key, oauth_grant an OAuth access token, integration_key a named integration key with fixed scopes created on https://0xinsider.com/developers. Before integration_key was added, these keys reported oauth_grant. */
7
+ credential_kind: "api_key" | "oauth_grant" | "integration_key";
7
8
  /** The credential is currently valid; revoked, expired or unknown credentials are rejected. */
8
9
  credential_status: "active";
9
10
  entitlement: {
@@ -11,7 +12,7 @@ export type AccountIdentity = {
11
12
  /** When paid data access is lapsed, the caller should renew the subscription; otherwise null. */
12
13
  recovery_action: "renew_subscription" | null;
13
14
  };
14
- /** Approved OAuth scopes; null for full developer-key access. */
15
+ /** The scopes an OAuth grant or integration key carries; null for full developer-key access. */
15
16
  scopes: string[] | null;
16
17
  };
17
18
  meta: ResponseMeta;
@@ -76,8 +77,8 @@ export type ApiError = {
76
77
  /** The recommended next request instant (RFC3339), always in the future. Present on every retryable error: `pick_not_released`, `rate_limited`, `rate_limit_unavailable`, and `read_model_warming`. Omitted otherwise. The absolute twin of `Retry-After`; prefer the header for the sleep duration. For `pick_not_released`, the earliest of the next scheduled release, the next automatic selector attempt, the operating-window start, or about 60 seconds. See that response. */
77
78
  retry_at?: string;
78
79
  freshness?: FreshnessFailure;
79
- /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
80
- reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
80
+ /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. cold_read_limited (429 rate_limited, #28752): the account has used its share of cold reads on GET /api/v1/market/{condition_id}/holders, requests for a market whose roster is not cached, each of which walks Polymarket (6 a minute, in bursts of up to 400); not the per-minute window, so a cached market still answers, and the next cold read is admitted at Retry-After. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
81
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "cold_read_limited" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
81
82
  };
82
83
  meta: ResponseMeta;
83
84
  };
@@ -90,8 +91,16 @@ export type ApiErrorBody = {
90
91
  /** The recommended next retry instant (RFC3339). Present on every retryable error (reason=pick_not_released, code=rate_limited including reason=monthly_quota_exceeded, code=rate_limit_unavailable, reason=read_model_warming) and omitted otherwise. Always in the future. For pick_not_released, the recommendation is advisory and can change before a pick becomes available. Schedule the next request from the returned value instead of inferring a release schedule or polling. Prefer Retry-After for the duration because it is immune to client clock skew. */
91
92
  retry_at?: string;
92
93
  freshness?: FreshnessFailure;
93
- /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
94
- reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
94
+ /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. cold_read_limited (429 rate_limited, #28752): the account has used its share of cold reads on GET /api/v1/market/{condition_id}/holders, requests for a market whose roster is not cached, each of which walks Polymarket (6 a minute, in bursts of up to 400); not the per-minute window, so a cached market still answers, and the next cold read is admitted at Retry-After. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
95
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "cold_read_limited" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
96
+ };
97
+ export type BatchGameHoldersItem = {
98
+ /** Zero-based request index. Duplicate inputs keep separate result rows. */
99
+ index: number;
100
+ input: string;
101
+ status: "ok" | "error";
102
+ data?: GameHoldersItem;
103
+ error?: ApiErrorBody;
95
104
  };
96
105
  export type BatchMarketFlowItem = {
97
106
  /** Zero-based request index. Duplicate inputs keep separate result rows. */
@@ -141,6 +150,22 @@ export type Candle = {
141
150
  /** Close price in provider [0, 1] units (last observed point in the bucket). */
142
151
  c: number;
143
152
  };
153
+ export type CategoryLeader = {
154
+ address: string;
155
+ as_of: string;
156
+ category: string;
157
+ edge_lower_bound: number | null;
158
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
159
+ id: string;
160
+ independent_events: number;
161
+ n_resolved: number | null;
162
+ platform: "polymarket";
163
+ pnl: number | null;
164
+ rank: number;
165
+ unresolved_events: number;
166
+ username: string | null;
167
+ win_rate: number | null;
168
+ };
144
169
  /** Model-wide readiness, read in the same database snapshot as category_records. Individual category rows retain their own status. */
145
170
  export type CategorySkillModelReadiness = {
146
171
  status: "live" | "insufficient" | "stale" | "unknown" | "degraded";
@@ -267,8 +292,6 @@ export type ComboFillsResponse = {
267
292
  /** Continuation offset for largest or payout ordering. */
268
293
  next_offset?: number;
269
294
  meta: ResponseMeta;
270
- /** Not computed for combo fill pages; omitted. */
271
- total?: number;
272
295
  };
273
296
  export type ComboLeg = {
274
297
  leg_index: number;
@@ -392,7 +415,8 @@ export type CounterpartyAnalysis = {
392
415
  };
393
416
  export type CounterpartyExecution = {
394
417
  execution_id: string;
395
- exchange_family: "ctf_v2" | "neg_risk_ctf_v2";
418
+ /** Polymarket exchange contract that emitted the execution: `ctf_v2` the CTF Exchange v2, `neg_risk_ctf_v2` the Neg Risk CTF Exchange v2, `exchange_v3` ExchangeV3, which settles Polymarket Protocol V2 binary and neg-risk markets. Treat an unknown value as another exchange. */
419
+ exchange_family: "ctf_v2" | "neg_risk_ctf_v2" | "exchange_v3";
396
420
  transaction_hash: string;
397
421
  orders_matched_log_index: number;
398
422
  taker: CounterpartyParticipant;
@@ -603,7 +627,7 @@ export type EdgeHunterObservation = {
603
627
  provider_read_source: "cached" | "live";
604
628
  /** True only when the provider page read for each outcome token listed every holder of that token. Observation collection reads one 100-row page per token; a token with more holders stays incomplete. False means holder counts and dollar totals measure the observed positive-holder subset. sharp_pct describes that observed subset and is not a lower bound on the full-population percentage. Incomplete scans cannot satisfy a future capital-promotion gate. */
605
629
  holder_scan_complete: boolean;
606
- /** Proven provider holder observation time. A warm cache hit uses only the original provider completion time from its companion metadata, never cache-read time. A wider_holder or emerging_pile row whose holder read did not finish in the current pass may reuse that market's last pregame holder page for up to 15 minutes; an in_play row may reuse its last in-play page, read after the provider reported the game live and never before that market's own kickoff, for up to 10 minutes. Both ages are counted when the snapshot is computed. Either reuse carries that page's original time here and provider_read_source cached. A pregame market more than an hour before kickoff reuses its last page the same way until that page is 10 minutes old, and only then is read again. Once that market's own kickoff has passed, an in_play row with provider_read_source cached, a warm hit or a reuse, never carries a page read before it. Null, malformed, future, or stale holder time fails in-play closed. */
630
+ /** Proven provider holder observation time. A warm cache hit uses only the original provider completion time from its companion metadata, never cache-read time. A wider_holder or emerging_pile row whose holder read did not finish or failed in the current pass may reuse that market's last pregame holder page for up to 15 minutes; an in_play row may reuse its last in-play page, read after the provider reported the game live and never before that market's own kickoff, for up to 10 minutes. Both ages are counted when the snapshot is computed. Either reuse carries that page's original time here and provider_read_source cached. A pregame market more than an hour before kickoff reuses its last page the same way until that page is 10 minutes old, and only then is read again; while that market has had no trade since the page, it keeps reusing the page until it is 30 minutes old. Once that market's own kickoff has passed, an in_play row with provider_read_source cached, a warm hit or a reuse, never carries a page read before it. Null, malformed, future, or stale holder time fails in-play closed. */
607
631
  holder_snapshot_at: string | null;
608
632
  /** Truthful state of the directional read, which classifies each graded holder by its fresh synced legs across the game's markets and, when holder_scan_complete is true, by Polymarket's currentValue on both outcomes of this market. A wider_holder row can remain emitted with unavailable and terminal wider_holder_emitted; in_play fails closed instead and terminates as in_play_directional_unavailable. */
609
633
  directional_status: "available" | "unknown_ungrouped" | "unknown_stale" | "unavailable";
@@ -622,7 +646,7 @@ export type EdgeHunterObservation = {
622
646
  export type EdgeHunterObservationCoverage = {
623
647
  /** Sum of canonical source-generation funnel input across all sports, before category, cohort or selector projection. */
624
648
  input_markets: number;
625
- /** Canonical source-generation input assigned capacity_limited. These markets were intentionally outside the bounded holder-work admission and are not missing emitted rows. */
649
+ /** Canonical source-generation input assigned capacity_limited. These markets were intentionally outside the bounded holder-work admission and are not missing emitted rows. It includes the admitted pregame wider_holder markets of any sport no request named in the last 30 minutes, whose holders the generation did not read. */
626
650
  capacity_limited_markets: number;
627
651
  /** All wider_holder and in_play observations emitted in the canonical source generation, before cohort, category or selector projection. Emerging pile is an overlapping projection and does not add source emissions. */
628
652
  emitted_observations: number;
@@ -655,7 +679,7 @@ export type EdgeHunterObservationDeparture = {
655
679
  last_observed_at: string;
656
680
  /** snapshot_as_of of the first snapshot of this selection without the card. */
657
681
  departed_at: string;
658
- /** Why the market has no card: its terminal in this selection's funnel in the snapshot it left, and while that terminal reports a read that did not finish (holder_deadline_unavailable, provider_unavailable, holder_computation_unavailable, internal_unclassified), the terminal of each later snapshot until one answers; an answered reason never changes. primary_slate_candidate: the market joined the funded slate, which view=signals covers. capacity_limited: it lost its evaluation place without another outcome. missing_stored_market: the market was no longer in the stored market universe. Any other value means what it means in the funnel, for example split_holder_pile, no_current_graded_holder or resolved. */
682
+ /** Why the market has no card: its terminal in this selection's funnel in the snapshot it left, and while that terminal reports a read that did not finish (holder_deadline_unavailable, provider_unavailable, holder_computation_unavailable, internal_unclassified), the terminal of each later snapshot until one answers; an answered reason stays, except as view=signals starts or stops listing the market. primary_slate_candidate: view=signals lists the market. While the entry stays, a later snapshot that read view=signals and no longer excludes the market replaces it with that snapshot's terminal, one that excludes the market replaces any other reason with it, and one with signals_as_of null leaves it as it is. capacity_limited: it lost its evaluation place without another outcome. missing_stored_market: the market was no longer in the stored market universe. Any other value means what it means in the funnel, for example split_holder_pile, no_current_graded_holder or resolved. */
659
683
  reason: EdgeHunterObservationTerminalReason;
660
684
  };
661
685
  /** Full Edge Hunter observations list envelope. Required degradation_reasons explains the source-generation verdict; required coverage distinguishes source input, intentional capacity exclusions, source emissions, incomplete holder scans, selection and the returned page. The view literal distinguishes advanced collections, including empty pages. */
@@ -679,10 +703,12 @@ export type EdgeHunterObservationsResponse = {
679
703
  selection?: EdgeHunterSelection;
680
704
  /** Echoes the opt-in admission rule a request named; omitted on a default read. When present, data, funnel, coverage, degraded and degradation_reasons describe that selection, not the default one. */
681
705
  admission?: "most_held_48h";
682
- /** cohort=wider_holder only, for the default selection and for admission=most_held_48h: markets that had a wider_holder card in an earlier snapshot of the same selection, have none in this one, and have not kicked off. Newest departed_at first. An entry stays until the game_start_time it carries passes, and leaves as soon as the market has a card again; while it stays only a reason that reports an unfinished read changes (see reason), and a later departure of the same market is a new entry. Filtered by the same category and selectors as data, and identical on every page of one snapshot. At most 336 entries; when more are open, the oldest departures leave first. An empty array means no card of this selection is departed. Omitted on in_play and emerging_pile, and on a snapshot that could not establish its departures, never reported as an empty array. Tracking that restarts after its record is lost starts empty. */
706
+ /** cohort=wider_holder only, for the default selection and for admission=most_held_48h: markets that had a wider_holder card in an earlier snapshot of the same selection, have none in this one, and have not kicked off. Newest departed_at first. An entry stays until the game_start_time it carries passes, and leaves as soon as the market has a card again; while it stays, its reason changes only while it reports an unfinished read or when view=signals starts or stops listing the market (see reason), and a later departure of the same market is a new entry. Filtered by the same category and selectors as data, and identical on every page of one snapshot. At most 336 entries; when more are open, the oldest departures leave first. An empty array means no card of this selection is departed. Omitted on in_play and emerging_pile, and on a snapshot that could not establish its departures, never reported as an empty array. Tracking that restarts after its record is lost starts empty. */
683
707
  departures?: EdgeHunterObservationDeparture[];
708
+ /** The ranked_at of the view=signals snapshot whose listed markets this snapshot excluded from wider_holder as primary_slate_candidate. The refresh that computed this snapshot read it as it started, so it can be one refresh older than the view=signals snapshot a reader sees at the same moment. null when no view=signals snapshot could be read: that refresh excluded no market, and the funnel counts no primary_slate_candidate. Omitted on an unmappable legacy category, which reads no generation. */
709
+ signals_as_of?: string | null;
684
710
  };
685
- /** Closed 25-value terminal-reason vocabulary for the accountable Edge Hunter observation funnel. capacity_limited is intentional bounded provider-work admission and does not itself set the snapshot degraded. board_source_unavailable is a completed board-source failure; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; both classify only already-started rows, so for the upcoming source read funnel.sports[].board_upcoming_status instead; provider_unavailable is reserved for an attempted holder-provider failure; holder_deadline_unavailable is holder cache/provider absolute-deadline exhaustion. */
711
+ /** Closed 25-value terminal-reason vocabulary for the accountable Edge Hunter observation funnel. capacity_limited is intentional bounded provider-work admission and does not itself set the snapshot degraded. board_source_unavailable is a completed board-source failure; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; both classify only already-started rows, so for the upcoming source read funnel.sports[].board_upcoming_status instead; provider_unavailable is reserved for a holder read sent to the provider that failed, with no reusable holder page; holder_deadline_unavailable is holder cache/provider absolute-deadline exhaustion or a holder read local capacity never sent, with no reusable holder page. */
686
712
  export type EdgeHunterObservationTerminalReason = "outside_horizon" | "resolved" | "provider_closed" | "provider_excluded" | "invalid_market" | "missing_token" | "missing_stored_market" | "not_provider_live" | "board_source_unavailable" | "board_deadline_unavailable" | "primary_slate_candidate" | "zero_indexed_holder_research" | "capacity_limited" | "provider_unavailable" | "holder_deadline_unavailable" | "holder_computation_unavailable" | "holder_scan_incomplete" | "no_current_graded_holder" | "split_holder_pile" | "price_unavailable" | "wider_holder_emitted" | "in_play_emitted" | "in_play_stale_observed" | "in_play_directional_unavailable" | "internal_unclassified";
687
713
  /** One provider outcome in fixed YES/NO order, including its frozen token identity and independently observed quote. Null current_price means no verified current quote is available. */
688
714
  export type EdgeHunterOutcome = {
@@ -702,6 +728,8 @@ export type EdgeHunterParticipant = {
702
728
  headshot_revision?: number;
703
729
  tour?: string;
704
730
  name: string;
731
+ logo_mark_light?: boolean;
732
+ logo_mark_measured?: boolean;
705
733
  };
706
734
  export type EdgeHunterPrice = {
707
735
  /** Provider probability as a decimal string. Keep its precision until display. */
@@ -877,15 +905,15 @@ export type EdgeHunterSportFunnelReport = {
877
905
  board_live_available: boolean;
878
906
  /** Whether a provider-backed upcoming-board source is configured and applicable for this sport. False means not applicable, not provider failure. */
879
907
  board_upcoming_configured: boolean;
880
- /** Whether every configured upcoming-board scope completed as available. False with board_upcoming_configured=false means not applicable. When board_upcoming_configured is true and this flag is false, read board_upcoming_status for the cause (it reads unknown, i.e. no recorded cause, only on a snapshot cached before that field existed, which self-clears within one TTL): the board_source_unavailable and board_deadline_unavailable terminals are assigned only to already-started rows (the live half) and are structurally 0 for the upcoming source, so they never explain this flag. */
908
+ /** Whether every configured upcoming-board scope completed as available. False with board_upcoming_configured=false means not applicable. When board_upcoming_configured is true and this flag is false, read board_upcoming_status for the cause (unknown means no cause was recorded, which no computed snapshot reports): the board_source_unavailable and board_deadline_unavailable terminals are assigned only to already-started rows (the live half) and are structurally 0 for the upcoming source, so they never explain this flag. */
881
909
  board_upcoming_available: boolean;
882
- /** Why the upcoming-board source is (un)available. Board supply is one canonical-sport union: the bare category owns live truth and every configured composed league scope contributes upcoming rows; folded leagues without a configured board (currently NCAAB and CFL) are not in the upcoming union. available: every configured scope completed truthfully (a successful empty schedule still counts). capacity_limited: provider pagination or a configured upcoming cache published an intentionally bounded complete-event prefix; those rows are excluded from diagnostic-universe input and must not be treated as a complete upcoming universe. Cache-bound prefixes are limited to an exact 5,000,000-byte final envelope. source_unavailable: composition failed before a truthful union; resolved scope readers turn half failures into cold_unavailable, so fresh producers are whole-union identity reconciliation or a registry contract failure and carry zero rows. cold_unavailable: every scope completed but at least one reported its upcoming half unavailable because no servable entry was inside the stale-serve bound and the background warm did not land in time; it is not by itself proof of a provider outage. deadline_unavailable: an internal configured-scope deadline or the outer bounded fair wave expired. An internal deadline may retain healthy bare-category or sibling-scope rows; the outer wave records zero rows. These upcoming fields do not describe league live-membership availability. If the bare-category live scope fails, all live rows are dropped even when a league scope completed, because the bare category is the sole live-truth owner. not_configured: no upcoming scope applies to the sport. unknown: exactly one cause -- a snapshot cached before this field existed whose legacy flags recorded an unavailable-but-configured half without saying why. Every freshly computed snapshot reports a concrete status, and a legacy available or not-configured row is reconstructed exactly, so unknown self-clears within one TTL. board_upcoming_available is exactly board_upcoming_status == available. */
910
+ /** Why the upcoming-board source is (un)available. Board supply is one canonical-sport union: the bare category owns live truth and every configured composed league scope contributes upcoming rows; folded leagues without a configured board (currently CFL) are not in the upcoming union. available: every configured scope completed truthfully (a successful empty schedule still counts). capacity_limited: provider pagination or a configured upcoming cache published an intentionally bounded complete-event prefix; those rows are excluded from diagnostic-universe input and must not be treated as a complete upcoming universe. Cache-bound prefixes are limited to an exact 5,000,000-byte final envelope. source_unavailable: composition failed before a truthful union; resolved scope readers turn half failures into cold_unavailable, so fresh producers are whole-union identity reconciliation or a registry contract failure and carry zero rows. cold_unavailable: every scope completed but at least one reported its upcoming half unavailable because no servable entry was inside the stale-serve bound and the background warm did not land in time; it is not by itself proof of a provider outage. deadline_unavailable: an internal configured-scope deadline or the outer bounded fair wave expired. An internal deadline may retain healthy bare-category or sibling-scope rows; the outer wave records zero rows. These upcoming fields do not describe league live-membership availability. If the bare-category live scope fails, all live rows are dropped even when a league scope completed, because the bare category is the sole live-truth owner. not_configured: no upcoming scope applies to the sport. unknown: no cause was recorded; every computed snapshot reports a concrete status, so none reads unknown. board_upcoming_available is exactly board_upcoming_status == available. */
883
911
  board_upcoming_status: "unknown" | "not_configured" | "available" | "capacity_limited" | "source_unavailable" | "cold_unavailable" | "deadline_unavailable";
884
- /** Configured upcoming scopes that did not complete as available. Values are category, a provider league tag slug (nfl, cfb, nba, wnba, euroleague-basketball, nhl, mls, valorant, league-of-legends, counter-strike-2, or dota-2), registry when the compiled scope/projection contract drifted, union when cross-scope identity reconciliation failed, or wave when the outer fair-wave deadline expired before scope-level evidence returned. Empty means no unavailable upcoming scope was identified; this includes healthy/not-configured rows and a legacy cached row. Observation league scopes are upcoming-only and perform no live-membership read. */
885
- board_upcoming_unavailable_scopes: ("category" | "nfl" | "cfb" | "nba" | "wnba" | "euroleague-basketball" | "nhl" | "mls" | "valorant" | "league-of-legends" | "counter-strike-2" | "dota-2" | "registry" | "union" | "wave")[];
912
+ /** Configured upcoming scopes that did not complete as available. Values are category, a provider league tag slug (nfl, cfb, nba, wnba, euroleague-basketball, ncaa-basketball, cwbb, nhl, mls, valorant, league-of-legends, counter-strike-2, or dota-2), registry when the compiled scope/projection contract drifted, union when cross-scope identity reconciliation failed, or wave when the outer fair-wave deadline expired before scope-level evidence returned. Empty means no unavailable upcoming scope was identified; this includes healthy/not-configured rows and a legacy cached row. Observation league scopes are upcoming-only and perform no live-membership read. */
913
+ board_upcoming_unavailable_scopes: ("category" | "nfl" | "cfb" | "nba" | "wnba" | "euroleague-basketball" | "ncaa-basketball" | "cwbb" | "nhl" | "mls" | "valorant" | "league-of-legends" | "counter-strike-2" | "dota-2" | "registry" | "union" | "wave")[];
886
914
  /** Stored-universe rows plus provider-board rows missing from storage. */
887
915
  input: number;
888
- /** Sparse counts over the closed 25-value terminal vocabulary: outside_horizon, resolved, provider_closed, provider_excluded, invalid_market, missing_token, missing_stored_market, not_provider_live, board_source_unavailable, board_deadline_unavailable, primary_slate_candidate, zero_indexed_holder_research, capacity_limited, provider_unavailable, holder_deadline_unavailable, holder_computation_unavailable, holder_scan_incomplete, no_current_graded_holder, split_holder_pile, price_unavailable, wider_holder_emitted, in_play_emitted, in_play_stale_observed, in_play_directional_unavailable, or internal_unclassified. primary_slate_candidate means exact admission by the funded route's raw shared signals query before provider/holder enrichment; recent-flow rows rejected by its event, bucket, or total caps remain eligible for wider_holder measurement. capacity_limited is intentional bounded provider-work admission, is fully accounted here, and does not itself set degraded=true. board_source_unavailable means a completed board source was unavailable; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; provider_unavailable means an attempted holder-provider read failed; holder_deadline_unavailable means holder cache/provider work missed the absolute request deadline; holder_computation_unavailable means post-holder provider or DB-backed price/metadata evaluation was unavailable. */
916
+ /** Sparse counts over the closed 25-value terminal vocabulary: outside_horizon, resolved, provider_closed, provider_excluded, invalid_market, missing_token, missing_stored_market, not_provider_live, board_source_unavailable, board_deadline_unavailable, primary_slate_candidate, zero_indexed_holder_research, capacity_limited, provider_unavailable, holder_deadline_unavailable, holder_computation_unavailable, holder_scan_incomplete, no_current_graded_holder, split_holder_pile, price_unavailable, wider_holder_emitted, in_play_emitted, in_play_stale_observed, in_play_directional_unavailable, or internal_unclassified. primary_slate_candidate means the view=signals snapshot named by signals_as_of lists the market at its widest selection (horizon_hours=48, min_grade=B, no selector), so it is not a wider_holder candidate; when no view=signals snapshot could be read (signals_as_of null), no market takes it. capacity_limited is intentional bounded provider-work admission, is fully accounted here, and does not itself set degraded=true. board_source_unavailable means a completed board source was unavailable; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; provider_unavailable means a holder read sent to the provider failed and the market had no reusable holder page; holder_deadline_unavailable means holder cache/provider work missed the absolute request deadline, or local capacity never sent the holder read, and the market had no reusable holder page; holder_computation_unavailable means post-holder provider or DB-backed price/metadata evaluation was unavailable. */
889
917
  terminals: Record<string, number>;
890
918
  /** Sum of every sparse terminal count. */
891
919
  terminal_total: number;
@@ -927,7 +955,6 @@ export type EventReplayMeta = {
927
955
  /** Unique request ID (req_ prefix). The same value as the X-Request-Id response header, the request's usage accounting row and its log lines. */
928
956
  request_id: string;
929
957
  cached: boolean;
930
- cache_age_s?: number;
931
958
  /** Advisory request weight (relative compute cost). 1 for simple reads; higher for heavier endpoints. Not a credit/price. */
932
959
  cost: number;
933
960
  replay: {
@@ -1005,8 +1032,12 @@ export type ExploreGroup = {
1005
1032
  markets: ExploreMarket[];
1006
1033
  /** The volume of the group's highest-volume market, which is markets[0]: the same figure as that market's volume, Polymarket's cumulative taker volume in shares rather than cash. Null when unavailable. */
1007
1034
  rep_volume: number | null;
1008
- /** Canonical key since #16304; rep_whales is its deprecated spelling, emitted beside it with the same value. */
1035
+ /** Canonical key since #16304; rep_whales is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1009
1036
  rep_large_trades: number | null;
1037
+ /**
1038
+ * Deprecated spelling of rep_large_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read rep_large_trades.
1039
+ * @deprecated
1040
+ */
1010
1041
  rep_whales: number | null;
1011
1042
  };
1012
1043
  export type ExploreMarket = {
@@ -1028,17 +1059,33 @@ export type ExploreMarket = {
1028
1059
  /** Polymarket's traded-volume figure for the market, as last stored: cumulative taker volume in shares, each counted at its $1 settlement value, not the cash that changed hands (100 shares bought at $0.40 add 100, not 40). It can lag Polymarket's current figure. sort=volume orders by it. Null when unavailable. */
1029
1060
  volume: number | null;
1030
1061
  liquidity: number | null;
1031
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
1062
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1032
1063
  large_trade_count: number | null;
1064
+ /**
1065
+ * Deprecated spelling of large_trade_count, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_count.
1066
+ * @deprecated
1067
+ */
1033
1068
  whale_trade_count: number | null;
1034
- /** Canonical key since #16304; whale_distinct_wallets is its deprecated spelling, emitted beside it with the same value. */
1069
+ /** Canonical key since #16304; whale_distinct_wallets is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1035
1070
  large_trade_distinct_wallets: number | null;
1071
+ /**
1072
+ * Deprecated spelling of large_trade_distinct_wallets, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_distinct_wallets.
1073
+ * @deprecated
1074
+ */
1036
1075
  whale_distinct_wallets: number | null;
1037
- /** Canonical key since #16304; whale_total_usd is its deprecated spelling, emitted beside it with the same value. */
1076
+ /** Canonical key since #16304; whale_total_usd is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1038
1077
  large_trade_total_usd: number | null;
1078
+ /**
1079
+ * Deprecated spelling of large_trade_total_usd, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_total_usd.
1080
+ * @deprecated
1081
+ */
1039
1082
  whale_total_usd: number | null;
1040
- /** Canonical key since #16304; whale_last_trade_at is its deprecated spelling, emitted beside it with the same value. */
1083
+ /** Canonical key since #16304; whale_last_trade_at is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1041
1084
  large_trade_last_at: string | null;
1085
+ /**
1086
+ * Deprecated spelling of large_trade_last_at, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_last_at.
1087
+ * @deprecated
1088
+ */
1042
1089
  whale_last_trade_at: string | null;
1043
1090
  end_date: string | null;
1044
1091
  created_at: string | null;
@@ -1075,15 +1122,19 @@ export type ExploreMarket = {
1075
1122
  discover_score: number | null;
1076
1123
  score_components: {
1077
1124
  volume_signal: number | null;
1078
- /** Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value. */
1125
+ /** Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1079
1126
  large_trade_signal: number | null;
1127
+ /**
1128
+ * Deprecated spelling of large_trade_signal, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_signal.
1129
+ * @deprecated
1130
+ */
1080
1131
  whale_signal: number | null;
1081
1132
  liquidity_signal: number | null;
1082
1133
  recency_signal: number | null;
1083
- /** Canonical key since #16308; smart_money_signal is its deprecated spelling, emitted beside it with the same value. */
1134
+ /** Canonical key since #16308; smart_money_signal is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1084
1135
  sharp_money_signal: number | null;
1085
1136
  /**
1086
- * Deprecated spelling of sharp_money_signal; emitted beside it with the same value and never removed.
1137
+ * Deprecated spelling of sharp_money_signal; emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read sharp_money_signal.
1087
1138
  * @deprecated
1088
1139
  */
1089
1140
  smart_money_signal: number | null;
@@ -1105,7 +1156,7 @@ export type ExportCompleteness = {
1105
1156
  sync_coverage: number;
1106
1157
  };
1107
1158
  export type ExportCounts = {
1108
- /** Daily P&L rows. The daily P&L covers every market of the wallet. */
1159
+ /** The days in the export file's pnl section, the wallet's sports and esports realized P&L by UTC day: the file's export_metadata.pnl_rows, at most its earliest 3650 days. 0 while source_range.pnl_series_status is pending, and 0 with it ready for a wallet that traded no sports or esports market. */
1109
1160
  pnl_days: number;
1110
1161
  /** The wallet's sports and esports markets: the rows of the export's markets section, before its 50,000-row cap. */
1111
1162
  exported_markets: number;
@@ -1149,23 +1200,30 @@ export type ExportJobReadyData = {
1149
1200
  data_as_of: string | null;
1150
1201
  };
1151
1202
  export type ExportSourceRange = {
1203
+ /** The first UTC day in the export file's pnl section, the wallet's sports and esports realized P&L by day: the file's export_metadata.pnl_date_from. Null when that section has no day, including while pnl_series_status is pending. */
1152
1204
  first_pnl_date: string | null;
1205
+ /** The last UTC day in the export file's pnl section: the file's export_metadata.pnl_date_to. Null when that section has no day. */
1153
1206
  last_pnl_date: string | null;
1207
+ /** Whether the export file's pnl section holds the wallet's sports and esports day series, the file's export_metadata.pnl_series_status. pending means 0xinsider has not computed the series yet: the dates are null and counts.pnl_days is 0, which then never means the wallet has no day. A wallet that traded no sports or esports market is ready with null dates and counts.pnl_days 0: it never gets a series, and with nothing stored completeness.status is empty (since 2026-10-29, #30620, #30657). */
1208
+ pnl_series_status: "ready" | "pending";
1154
1209
  /** The latest trade in the wallet's sports and esports markets. Null when it has none. */
1155
1210
  latest_trade_at: string | null;
1156
1211
  /** Same instant as latest_trade_at: the latest activity of the markets the export holds. */
1157
1212
  latest_market_activity_at: string | null;
1158
1213
  };
1159
1214
  export type ExportVolumeReconciliation = {
1160
- /** Verified full-history both-sides USD cash volume. Null without coverage; the local activity numerator may cover only a subset of history. */
1215
+ /**
1216
+ * Deprecated (#30499): always null since 2026-10-29. It held Polymarket's volume across every market of the wallet, which reconciles nothing against the sports and esports exported_activity_volume; the key stays so existing V1 clients keep parsing. Read exported_activity_volume for the wallet's sports and esports volume.
1217
+ * @deprecated
1218
+ */
1161
1219
  provider_lifetime_volume: number | null;
1162
- /** Cash in USD, buys and sells, summed over the daily P&L rows this export carries, from the fills 0xinsider has stored for the wallet. It can cover less history than provider_lifetime_volume; never Polymarket's share count. */
1163
- exported_activity_volume: number;
1220
+ /** Volume in USD, buys and sells, in sports and esports markets, each fill's size times its price with fees excluded, summed over the wallet's stored daily volume rows (from the fills 0xinsider stores for the wallet): the export file's summary.volume_reconciliation.exported_activity_volume, not the sum of its pnl[].total_volume, which is null on a day the trade rollups do not cover. Never Polymarket's share count. Null when any of those rows has no volume: a sum over the other days would be a partial subtotal. */
1221
+ exported_activity_volume: number | null;
1164
1222
  /** Cost basis in USD summed over the wallet's sports and esports markets, the markets section of the export. */
1165
1223
  exported_market_cost_basis: number;
1166
- /** provider_lifetime_volume minus exported_activity_volume, in USD, rounded to cents. Null when provider_lifetime_volume is null. */
1224
+ /** Always null. provider_lifetime_volume covered every market and exported_activity_volume sports and esports markets only, so their difference measured nothing; the field stays so existing clients keep parsing the object. */
1167
1225
  provider_activity_volume_gap: number | null;
1168
- /** exported_activity_volume divided by provider_lifetime_volume, a fraction of the cash, not a percent. Null when provider_lifetime_volume is null or zero. */
1226
+ /** Always null, for the same reason as provider_activity_volume_gap. */
1169
1227
  activity_volume_coverage: number | null;
1170
1228
  };
1171
1229
  export type FreshnessFailure = {
@@ -1178,7 +1236,7 @@ export type FreshnessFailure = {
1178
1236
  /** The trader body's whole-response data-quality status. Only fresh can satisfy max_age_s. */
1179
1237
  data_quality_status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
1180
1238
  };
1181
- /** One sports or esports game: both sides, its schedule, provider status, linked Polymarket markets and their available provider moneyline price states. Assembled from the same provider-first live and upcoming projections the site's boards use, with no request-time provider fan-out. */
1239
+ /** One sports or esports game: both sides, its schedule, provider status, its winner markets (the moneyline, or the soccer 1X2 legs) with their available provider moneyline price states and liquidity, and the game's traded volume. The event's other markets are on GET /api/v1/games/{event_slug}/markets. Assembled from the same provider-first live and upcoming projections the site's boards use, with no request-time provider fan-out. */
1182
1240
  export type Game = {
1183
1241
  object: "game";
1184
1242
  /** The game's identity, for example mlb-mil-cin-2026-06-22. The same key the live_sports_updated webhook pulse carries and the same key /api/v1/games/{event_slug} takes. */
@@ -1200,12 +1258,15 @@ export type Game = {
1200
1258
  series_format?: string;
1201
1259
  /** Whether this read includes a market classified as paying on a draw, including soccer's independent 1X2 draw leg. Read this instead of assuming a two-outcome moneyline. */
1202
1260
  draw_offered: boolean;
1203
- /** Every market this read linked to the game, ordered by condition_id. */
1261
+ /** The game's winner markets the sports board binds to its sides (the moneyline, or a soccer game's three 1X2 legs), ordered by condition_id. Spreads, totals, period lines and props are on GET /api/v1/games/{event_slug}/markets. */
1204
1262
  markets: GameMarket[];
1205
1263
  freshness: GameFreshness;
1206
1264
  coverage: GameCoverage;
1207
1265
  /** The game's page on 0xinsider. */
1208
1266
  url: string;
1267
+ sharp_money?: GameSharpMoney;
1268
+ /** The game's traded volume, the figure the sports board carries for it, with its source, basis, unit and observation clock. A client can rank or filter games by volume.value. Omitted when the board carries no volume for the game, and on a finished game read from its stored record (freshness.source stored); never 0 in place of a missing figure. */
1269
+ volume?: GameVolume;
1209
1270
  };
1210
1271
  /** One side of the game. */
1211
1272
  export type GameCompetitor = {
@@ -1222,7 +1283,7 @@ export type GameCompetitor = {
1222
1283
  };
1223
1284
  /** What this game's read actually supplied, so a client branches on coverage instead of on a missing key. */
1224
1285
  export type GameCoverage = {
1225
- /** available when a live-score frame supplied this game's scores. */
1286
+ /** available when a live-score frame supplied a score for this game. A game no live-score feed has reported yet, as most scheduled games are, reads unavailable. */
1226
1287
  scores: "available" | "unavailable";
1227
1288
  /** provider_ids when every side carries a provider id, labels when only the provider's names identify them, unavailable when neither exists. Do not join on names when this reads labels. */
1228
1289
  competitors: "provider_ids" | "labels" | "unavailable";
@@ -1231,15 +1292,15 @@ export type GameCoverage = {
1231
1292
  };
1232
1293
  /** How current this game's facts are. Independent per source: the board half that produced the game, and the live-score frame that produced its scores. */
1233
1294
  export type GameFreshness = {
1234
- /** Which board half produced this game. */
1235
- source: "live" | "upcoming";
1295
+ /** What produced this game: live or upcoming, the board half that carried it, or stored, the stored record of a finished game that has left the board (GET /api/v1/games/{event_slug}, and GET /api/v1/games with a finished status). */
1296
+ source: "live" | "upcoming" | "stored";
1236
1297
  /** Whether that half returned a truthful source body for this read. */
1237
1298
  source_status: "ok" | "unavailable";
1238
1299
  /** Whether that half had a source body at all. not_applicable means the sport has no configured source for that half. */
1239
1300
  source_availability: "available" | "unavailable" | "not_applicable";
1240
- /** Freshness of the cached source body, never inferred from the response clock or the row count. */
1301
+ /** Freshness of the cached source body, never inferred from the response clock or the row count. not_applicable for a stored game, whose record is final. */
1241
1302
  source_freshness: "fresh" | "stale" | "unknown" | "not_applicable";
1242
- /** The source body's data vintage. Omitted when the read has no vintage anchor, which is not age zero. */
1303
+ /** The source body's data vintage. Omitted when the read has no vintage anchor, which is not age zero. For a stored game, the later of its last live-score write and its last leg settlement. */
1243
1304
  source_observed_at?: string;
1244
1305
  /** Age of source_observed_at in seconds, capped at 600. Omitted past the cap or with no anchor. */
1245
1306
  source_age_seconds?: number;
@@ -1250,6 +1311,22 @@ export type GameFreshness = {
1250
1311
  /** The provider's own frame clock. Omitted when the frame carries none. */
1251
1312
  scores_source_at?: string;
1252
1313
  };
1314
+ /** One market of a game holders batch: GET /api/v1/market/{condition_id}/holders unfiltered and cut to the batch limit. */
1315
+ export type GameHoldersItem = {
1316
+ /** The roster's top holders by current value, at most limit. */
1317
+ data: MarketHolder[];
1318
+ /** More graded holders than limit: page them on GET /api/v1/market/{condition_id}/holders. */
1319
+ has_more: boolean;
1320
+ /** Graded holders in the roster, across every page. */
1321
+ total: number;
1322
+ market: MarketHoldersMarket;
1323
+ scan: MarketHoldersScan;
1324
+ totals: MarketHoldersTotals;
1325
+ /** When this roster was computed. A cached roster is at most 60 seconds old. */
1326
+ computed_at: string;
1327
+ /** true when the roster came from the 60-second roster cache. */
1328
+ cached: boolean;
1329
+ };
1253
1330
  /** One Polymarket market linked to this game. */
1254
1331
  export type GameMarket = {
1255
1332
  /** The mkt_-prefixed market id every other V1 response uses. */
@@ -1272,6 +1349,17 @@ export type GameMarket = {
1272
1349
  outcome_token_ids?: string[];
1273
1350
  /** Default provider moneyline state. Omitted when this market has no classified moneyline projection; incomplete and invalid projections remain explicit. */
1274
1351
  prices?: GameMarketPrices;
1352
+ /** Polymarket's reported liquidity for this market. Omitted when the provider read carried none, and on a finished game read from its stored record; never 0 in place of a missing figure. */
1353
+ liquidity?: GameMarketLiquidity;
1354
+ };
1355
+ /** One market's liquidity as Polymarket reports it (Gamma liquidityNum), verbatim. Polymarket documents it only as reported market liquidity, with no unit. It describes the market's resting order book, not traded volume. */
1356
+ export type GameMarketLiquidity = {
1357
+ /** The provider's figure at full precision. */
1358
+ value: number;
1359
+ /** Always gamma: the Polymarket Gamma API. */
1360
+ source: "gamma";
1361
+ /** When 0xinsider read the sports board body this figure came from, never a provider-authored timestamp. Omitted when that read has no clock. */
1362
+ observed_at?: string;
1275
1363
  };
1276
1364
  /** How the existing sports-board writer bound prices to competitors. */
1277
1365
  export type GameMarketPriceBindingProvenance = "provider_ids" | "exact_labels" | "containment_labels" | "elimination";
@@ -1332,28 +1420,132 @@ export type GameMarketProviderPrices = GameMarketPricePaired | GameMarketPriceIn
1332
1420
  export type GamesCoverage = {
1333
1421
  /** Canonical sport buckets served, sorted. */
1334
1422
  sports: string[];
1335
- /** League tags served, sorted. EuroLeague is euroleague under the Basketball sport bucket. */
1423
+ /** League tags served, sorted. EuroLeague is euroleague, NCAA men's college basketball cbb and NCAA women's college basketball cwbb, all under the Basketball sport bucket. */
1336
1424
  leagues: string[];
1337
1425
  /** Scopes whose source half was unavailable for this read, as <sport>:<half>. Empty means every scope answered. */
1338
1426
  sources_unavailable: string[];
1339
1427
  };
1428
+ /** Event-level sharp money for one game. Every aggregate field is null unless status is computed; null means unknown, never zero. */
1429
+ export type GameSharpMoney = {
1430
+ allocation: "exact" | "degraded" | null;
1431
+ computed_at: string | null;
1432
+ event_slug: string;
1433
+ holders_partial: boolean | null;
1434
+ lifecycle: "live" | "settled" | "indeterminate" | null;
1435
+ money_as_of: string | null;
1436
+ object: string;
1437
+ outcomes: ({
1438
+ is_leader: boolean;
1439
+ label: string;
1440
+ pct: number;
1441
+ side: "home" | "draw" | "away";
1442
+ usd: number;
1443
+ wallets: {
1444
+ a: number;
1445
+ b: number;
1446
+ s: number;
1447
+ };
1448
+ })[];
1449
+ status: "computed" | "not_computed" | "unavailable";
1450
+ total_usd: number | null;
1451
+ trader_count: number | null;
1452
+ unallocated_usd: number | null;
1453
+ verdict: {
1454
+ kind: "no_sharp_money";
1455
+ } | {
1456
+ kind: "all_on";
1457
+ label: string;
1458
+ } | {
1459
+ kind: "split";
1460
+ } | {
1461
+ kind: "leans";
1462
+ label: string;
1463
+ pct: number;
1464
+ } | {
1465
+ kind: "unavailable";
1466
+ } | {
1467
+ divergence_pts: number;
1468
+ kind: "leans_over_price";
1469
+ label: string;
1470
+ } | {
1471
+ kind: "no_clear_lean";
1472
+ } | {
1473
+ kind: "withheld";
1474
+ } | null;
1475
+ };
1340
1476
  /** Where the game is in its own life, as the provider reports it. A postponement, a cancellation and a suspension each keep their own state, so a client can tell a game that will be played later from one that never will be. */
1341
1477
  export type GameStatus = {
1342
- /** scheduled: kickoff is ahead or the provider still calls it scheduled. live: the provider reports it in play. paused: halftime or a provider-reported break. ended: the provider reported a final, an award or a forfeit. postponed, cancelled, suspended, delayed: the provider's own verdict, kept distinct. unknown: no provider state reached this read. A kickoff in the past is never read as live on its own. */
1478
+ /** scheduled: kickoff is ahead, or the provider still lists the game open and neither in play nor ended. With no live-score frame a game stays scheduled past its kickoff until the provider says otherwise. live: the provider reports it in play. paused: halftime or a provider-reported break. ended: the provider reported a final, an award or a forfeit. postponed, cancelled, suspended, delayed: the provider's own verdict, kept distinct. A tennis match that the provider still lists in play, with no live score feed and no change of period or score for 3 hours, also reads suspended. unknown: no provider state reached this read. A kickoff in the past is never read as live on its own. */
1343
1479
  state: "scheduled" | "live" | "paused" | "ended" | "postponed" | "cancelled" | "suspended" | "delayed" | "unknown";
1344
- /** The provider status folded onto one vocabulary across leagues. unknown means the provider sent a value this API has no meaning for; provider_status keeps that value verbatim. Omitted when no live-score frame carries a status. */
1480
+ /** The provider status folded onto one vocabulary across leagues. unknown means the provider sent a value this API has no meaning for; provider_status keeps that value verbatim. Omitted when no live-score frame carries a status, as for a listed game no live-score feed has reported yet. */
1345
1481
  match_status?: "scheduled" | "in_progress" | "halftime" | "penalty_shootout" | "delayed" | "suspended" | "final" | "final_overtime" | "final_shootout" | "awarded" | "forfeit" | "not_necessary" | "postponed" | "cancelled" | "unknown";
1346
- /** The provider's status string, verbatim. Omitted when the provider sent none. */
1482
+ /** The live-score feed's status string, verbatim. Omitted when no live-score frame carries one. This API never puts a label of its own here, such as Scheduled for a listed game. */
1347
1483
  provider_status?: string;
1348
1484
  /** The provider's period label, for example Q3, End Q2 or T5. Omitted when the provider sent none. */
1349
1485
  period?: string;
1350
1486
  /** The game clock as the provider spells it, never reformatted. Omitted when the provider sent none. */
1351
1487
  clock?: string;
1352
- /** Whether the game is in play. It is the provider's own in-play flag, except that a game the provider reports suspended (period SUS) or rescheduled to a later kickoff reads false. Omitted when no live-score frame exists, which is not the same as false. */
1488
+ /** Whether the game is in play. It is the provider's own in-play flag, except that three cases read false: a game the provider reports suspended (period SUS), a game rescheduled to a later kickoff, and a tennis match that the provider still lists in play with no live score feed and no change of period or score for 3 hours. Omitted when no live-score frame exists, which is not the same as false. */
1353
1489
  live?: boolean;
1354
1490
  /** Whether the game is over. Always present. */
1355
1491
  ended: boolean;
1356
1492
  };
1493
+ /** One fill in a game, as the game page's activity list shows it. */
1494
+ export type GameTrade = {
1495
+ /** Stable fill identity: {transaction_hash}:{token_id}:{wallet}:{shares}. Deduplicate on it across polls. */
1496
+ id: string;
1497
+ /** When the fill happened, to the second. */
1498
+ traded_at: string;
1499
+ /** The provider's side of the fill. */
1500
+ side: "BUY" | "SELL";
1501
+ /** The traded outcome's label; null when the provider named none. */
1502
+ outcome: string | null;
1503
+ /** 0 for the first (Yes) outcome token, 1 for the second (No); null when the provider did not say. */
1504
+ outcome_index: number | null;
1505
+ /** Fill price, 0 to 1. */
1506
+ price: number;
1507
+ /** Shares filled. */
1508
+ shares: number;
1509
+ /** USDC notional of the fill. */
1510
+ size_usd: number;
1511
+ /** The signed handicap the fill's side carries on a spread line, for example -1.5 or 1.5; null off spreads. */
1512
+ point: number | null;
1513
+ trader: {
1514
+ /** Lowercase proxy wallet. */
1515
+ address: string;
1516
+ /** The name the site shows: the 0xinsider username, else the provider's name or pseudonym, else the shortened address. */
1517
+ display_name: string;
1518
+ /** The trader's grade today; null for an ungraded or untracked wallet. */
1519
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
1520
+ };
1521
+ market: {
1522
+ /** The market's v1 id, mkt_ plus the condition_id. */
1523
+ id: string;
1524
+ /** The raw provider condition_id. */
1525
+ condition_id: string;
1526
+ /** The market's question. */
1527
+ title: string | null;
1528
+ /** The market's page slug. */
1529
+ slug: string | null;
1530
+ /** The market's name within the game, for example Draw, O/U 2.5, First to Score: CD Guadalajara, Game 2: Any Player Quadra Kill. */
1531
+ line_label: string | null;
1532
+ };
1533
+ };
1534
+ /** A game's traded volume as Polymarket reports it, read by the sports board with no request-time provider call. A one-side taker share count, the number Polymarket's own pages print behind a dollar sign, not the cash that changed hands. */
1535
+ export type GameVolume = {
1536
+ /** The volume at full precision, in unit. */
1537
+ value: number;
1538
+ /** taker_shares: cumulative one-side taker volume in shares. One share pays $1 at settlement, so this is not cash traded. Omitted only on a figure observed before units were recorded; never assume cash. */
1539
+ unit?: "taker_shares";
1540
+ /** game_lines: the game volume Polymarket's game page states, summed over the game's own lines. event_total: the whole event's volume, stated when no game volume was readable. The two can differ in either direction. Omitted when the basis is unknown. */
1541
+ basis?: "game_lines" | "event_total";
1542
+ /** The Polymarket API the figure was read from: polymarket_data (the Data API's live volume) or gamma (the Gamma API). */
1543
+ source: "polymarket_data" | "gamma";
1544
+ /** When 0xinsider read the figure from the provider, never a provider-authored timestamp. Omitted when no read time is held for it. */
1545
+ observed_at?: string;
1546
+ /** How long after observed_at 0xinsider treats the figure as current: 60 or 300 by source and basis, or 3600 for an older figure kept because a later read of the same total was lower or missing (a cumulative volume never falls). */
1547
+ fresh_for_seconds: number;
1548
+ };
1357
1549
  /** Current category evidence, independent of the global grade. Pick of the Day stamps only the served display roster; frozen entry snapshots remain unchanged. */
1358
1550
  export type HolderCategoryEvidence = {
1359
1551
  status: "live" | "insufficient" | "stale" | "unknown" | "degraded";
@@ -1380,9 +1572,20 @@ export type LargeExportPolicy = {
1380
1572
  /** How long a finished export is retained before expiry. */
1381
1573
  retention: string;
1382
1574
  };
1383
- direct_streaming: Record<string, unknown>;
1384
- async_job: Record<string, unknown>;
1385
- rate_limit: Record<string, unknown>;
1575
+ direct_streaming: {
1576
+ available_when: string;
1577
+ backpressure: string;
1578
+ chunk_size_rows: number;
1579
+ };
1580
+ async_job: {
1581
+ available_when: string;
1582
+ status_values: string[];
1583
+ retention: string;
1584
+ };
1585
+ rate_limit: {
1586
+ daily_cap_per_user: number;
1587
+ per_address_hourly_cap: number;
1588
+ };
1386
1589
  };
1387
1590
  export type LargePosition = {
1388
1591
  /** Composite prefixed ID `pos_<wallet>:<condition_id>:<outcome_index>`. */
@@ -1440,9 +1643,16 @@ export type LargePosition = {
1440
1643
  address: string;
1441
1644
  username?: string;
1442
1645
  grade?: "S" | "A" | "B" | "C" | "D" | "F";
1646
+ /** Sports and esports win rate as a ratio from 0 to 1 (0.62 means 62%): wins over the decided sports and esports markets on the wallet's record, the same figure as pnl.in_scope.win_rate on GET /api/v1/trader/{address}. Since 2026-10-27 it no longer counts other markets (#29953). Absent when the wallet has no record or no decided market. */
1443
1647
  win_rate?: number;
1444
- /** Polymarket's net total P&L for the wallet in USD: native Polymarket position P&L across all markets, fees included, plus credited maker and taker rebates. The 0xinsider profile's Total P&L is this figure unless the wallet has a published correction for neg-risk conversions, which GET /api/v1/trader/{address} serves as pnl.correction; the profile then shows pnl.correction.net_total. Distinct from this position's position_unrealized_pnl. Omitted when the wallet has no native accounting snapshot. */
1648
+ /**
1649
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's net total P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29953). Read trader.in_scope_realized_pnl.
1650
+ * @deprecated
1651
+ */
1445
1652
  pnl?: number;
1653
+ /** The wallet's realized P&L in USD on sports and esports markets, the figure the 0xinsider profile shows: the record behind pnl.in_scope.realized_pnl on GET /api/v1/trader/{address}, to cents. Distinct from this position's position_unrealized_pnl. For a graded wallet it is read from the latest grading pass, so it can trail that figure until the next pass. Omitted until 0xinsider has computed the wallet's record (#29953). */
1654
+ in_scope_realized_pnl?: number;
1655
+ /** Sports and esports markets on the wallet's record, pnl.in_scope.markets on GET /api/v1/trader/{address}. Since 2026-10-27 it no longer counts other markets (#29953). Absent when the wallet has no record. */
1446
1656
  markets_traded?: number;
1447
1657
  };
1448
1658
  market: {
@@ -1474,14 +1684,14 @@ export type LargeTrade = {
1474
1684
  /** Current trade review score on a 0..1 scale; higher values indicate a stronger review signal. This is the current response value and can differ from the recorded score. Missing measurements remain unavailable. */
1475
1685
  review_score: number;
1476
1686
  /**
1477
- * Deprecated alias of review_score with the same current value and 0..1 scale.
1687
+ * Deprecated alias of review_score with the same current value and 0..1 scale. Sunset 2027-02-01 (#29352): removed from V1 on that date; read review_score.
1478
1688
  * @deprecated
1479
1689
  */
1480
1690
  signal_score: number;
1481
1691
  /** 0.0–1.0 review score written once when the trade row is inserted, from the trader's statistics at that moment. Populated from 2026-08-03T11:59Z; older rows return null and are never backfilled, because a backfill could only read today's statistics. If a trade is added later, its time-sensitive recorded score reflects that delay. Canonical since #16311; recorded_signal_score carries the same value. */
1482
1692
  recorded_review_score: number | null;
1483
1693
  /**
1484
- * 0.0–1.0 review score written once when the trade row is inserted; null before 2026-08-03T11:59Z. Deprecated (#16311): `recorded_review_score` is the canonical spelling and carries the same value; this key stays on the wire.
1694
+ * 0.0–1.0 review score written once when the trade row is inserted; null before 2026-08-03T11:59Z. Deprecated (#16311): `recorded_review_score` is the canonical spelling and carries the same value; this key stays on the wire until its sunset on 2027-02-01 (#29352), when it is removed.
1485
1695
  * @deprecated
1486
1696
  */
1487
1697
  recorded_signal_score: number | null;
@@ -1496,7 +1706,7 @@ export type LargeTrade = {
1496
1706
  address: string;
1497
1707
  username?: string;
1498
1708
  /** The trader's grade today, on every row however old. For what the grade was when the trade happened, read grade_at_trade. */
1499
- grade?: string;
1709
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
1500
1710
  /** The grade the trader held when the trade happened, from recorded grade history (recorded from 2026-09-19T23:00Z). Null unless grade_at_trade_status is graded. Never today's grade projected backward. */
1501
1711
  grade_at_trade: "S" | "A" | "B" | "C" | "D" | "F" | null;
1502
1712
  /** graded: grade_at_trade holds the recorded grade. ungraded: the trader was recorded without a grade at that moment. unknown: no record covers the moment, which is every trade before 2026-09-19T23:00Z and a trade that fell between a grade change and its confirmation. unknown never means ungraded. */
@@ -1558,7 +1768,7 @@ export type LargeTradeInsertedV2Data = {
1558
1768
  traded_at: string;
1559
1769
  platform: "polymarket";
1560
1770
  };
1561
- /** `large_trades_inserted` data (Pro and Max): new large trades were ingested. It carries a count and no trade; subscribe to `large_trade_inserted_v2` for the trade itself. The deprecated spelling `whale_trades_inserted` delivers the same object. */
1771
+ /** `large_trades_inserted` data (Pro and Max): new large trades were ingested. It carries a count and no trade; subscribe to `large_trade_inserted_v2` for the trade itself. The deprecated spelling `whale_trades_inserted` delivers the same object until its sunset on 2027-02-01 (#29352). */
1562
1772
  export type LargeTradesInsertedData = {
1563
1773
  /** Large trades the producing batch admitted. */
1564
1774
  count: number;
@@ -1578,27 +1788,73 @@ export type LeaderboardEntry = {
1578
1788
  id: string;
1579
1789
  address: string;
1580
1790
  username?: string;
1581
- grade?: string;
1791
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
1582
1792
  /** Hot-streak tier (trailing-7d cross-sectional percentile); a separate axis from the all-time grade. Omitted when there is no recent activity. */
1583
1793
  streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
1584
1794
  score?: number;
1585
- /** Polymarket's all-time leaderboard P&L in USD, from Polymarket's latest observation of this wallet on its all-time leaderboard (dated by the leaderboard_pnl data_quality group). Omitted when that leaderboard has no current observation ranking the wallet; 0xinsider requests one, and never serves an older stored figure in its place. Includes unrealized open positions. Kept for back-compat. Not the profile's Total P&L, which GET /api/v1/trader/{address} serves as pnl.net_total; the two can differ by a wide margin. Prefer realized_pnl for the banked figure. */
1795
+ /**
1796
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's all-time leaderboard P&L, which covered every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29971). Read in_scope.realized_pnl.
1797
+ * @deprecated
1798
+ */
1586
1799
  pnl?: number;
1587
- /** Native realized P&L plus credited maker and taker rebates in USD, with fees already included. The exact numeric value is truncated toward zero to cents before JSON conversion. Omitted when the wallet has no native snapshot or the snapshot has no net realized value; never filled from another P&L basis. */
1800
+ /**
1801
+ * Deprecated since 2026-10-27 and never sent. It was native Polymarket realized P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29971). Read in_scope.realized_pnl.
1802
+ * @deprecated
1803
+ */
1588
1804
  realized_pnl?: number;
1589
- /** The 0xinsider correction to Polymarket's P&L for neg-risk conversions. Present only when one is published; realized_pnl keeps Polymarket's own figure and pnl_correction.realized adds the amount to it. The grade and the ranking use the corrected figure. net_total is omitted here. */
1805
+ /**
1806
+ * Deprecated since 2026-10-27 and never sent. It was the neg-risk conversion correction to the wallet-wide realized_pnl (#29971). Its sports and esports part is inside in_scope.realized_pnl.
1807
+ * @deprecated
1808
+ */
1590
1809
  pnl_correction?: PnlCorrection;
1591
- /** Full-history both-sides USD cash volume from a verified Polymarket user-volume observation. Omitted without coverage. */
1810
+ /**
1811
+ * Deprecated since 2026-10-27 and never sent. It was full-history USD cash volume over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29971).
1812
+ * @deprecated
1813
+ */
1592
1814
  volume?: number;
1815
+ /** Sports and esports markets on the wallet's record, the same count as in_scope.markets. Since 2026-10-27 (#29971); before, it counted every Polymarket market. Sent exactly when in_scope is. */
1593
1816
  markets_traded?: number;
1594
- /** The wallet's win rate across ALL categories, not the filtered one. ?category= decides WHICH wallets are listed (the wallet must be ranked in that category); it does not rescope this field, so a soccer-filtered list still reports each wallet's overall rate. For a per-category record use GET /api/v1/trader/{address}/categories. */
1817
+ /** The wallet's sports and esports win rate, in_scope.win_rate rounded to four places. Since 2026-10-27 (#29971); before, it covered every Polymarket market. ?category= decides WHICH wallets are listed (the wallet must be ranked in that category); it does not rescope this field. For a per-category record use GET /api/v1/trader/{address}/categories. Omitted when in_scope is omitted or has no win rate. */
1595
1818
  win_rate?: number;
1819
+ /** Additive (#27859): the wallet's sports and esports record, the same object as GET /api/v1/trader/{address} pnl.in_scope, as of the leaderboard's last refresh. The 0xinsider leaderboard page shows and sorts by in_scope.realized_pnl and in_scope.win_rate. Omitted until 0xinsider has computed the wallet's record; absent means not computed yet, never zero. */
1820
+ in_scope?: TraderPnlInScope;
1821
+ /** Additive (#32270): the wallet's edge over the price paid on its sports and esports markets, the figures the 0xinsider leaderboard page's Edge column states for the row. sort=edge orders by price_edge.edge. Omitted when the wallet has no settled sports or esports market of $20 or more at a known entry price. */
1822
+ price_edge?: LeaderboardPriceEdge;
1596
1823
  /** Observed trading style identifier. New rows use two_sided, category_focused, high_activity, diversified, mixed, or unclassified, counted over the wallet's sports and esports markets only. Historical identifiers remain readable during normal reclassification; style does not predict skill or intent. */
1597
1824
  strategy_type?: string;
1598
1825
  /** Provider platform. Always polymarket. */
1599
1826
  platform: "polymarket";
1827
+ /** When the wallet last traded: its most recent recorded trade, as of the leaderboard row's last refresh, which re-reads it hourly, so a new trade can take about an hour to show. It agrees with the activity filter: every wallet listed under activity=inactive last traded more than 30 days ago. Since 2026-11-02 (#32322); before, it carried the time 0xinsider last synced the wallet, usually within the past week whether or not the wallet traded. Omitted when the wallet has no recorded trade. */
1600
1828
  last_active?: string;
1601
1829
  };
1830
+ export type LeaderboardLeagues = {
1831
+ leagues: {
1832
+ category: string;
1833
+ name: string;
1834
+ ranked_traders: number;
1835
+ slug: string;
1836
+ sport: string;
1837
+ total_traders: number;
1838
+ }[];
1839
+ min_ranked: number;
1840
+ min_resolved: number;
1841
+ refreshed_at: string;
1842
+ };
1843
+ /** Edge over the price paid (#32270): how often the side a wallet bought won, minus the average price it paid, over its settled sports and esports markets of $20 or more at a known entry price. Probabilities throughout: edge 0.12 is 12 percentage points. A wallet buying at 99 cents that wins every market has an edge of about 0.01. A market bought on both sides counts by its shares: the winning side's share of the shares bought is its hit, the cost over those shares its price. */
1844
+ export type LeaderboardPriceEdge = {
1845
+ /** Settled sports and esports markets of $20 or more at a known entry price that the edge is measured over. */
1846
+ markets: number;
1847
+ /** Share of those markets whose bought side won, 0-1. */
1848
+ hit_rate: number;
1849
+ /** Mean entry price paid, 0-1. */
1850
+ avg_price: number;
1851
+ /** hit_rate minus avg_price, full precision. The value sort=edge orders by. */
1852
+ edge: number;
1853
+ /** Whether the edge ranks. ranked: at least 30 such markets, and the share of the decided ones that made money at settlement within 10 points of the win rate over the same markets. too_few_markets: fewer than 30. sample_mismatch: that share is more than 10 points away, so these markets do not describe the wallet's record. Only a ranked edge with no hold orders on sort=edge. */
1854
+ status: "ranked" | "too_few_markets" | "sample_mismatch";
1855
+ /** Why the leaderboard does not rank a ranked edge. record_incomplete: the wallet's stored sports and esports record shows more profit than Polymarket reports for it, so some losing markets are likely missing. Omitted when nothing holds the edge, and always omitted unless status is ranked. */
1856
+ hold?: "record_incomplete";
1857
+ };
1602
1858
  /** One side's score line inside a `live_sports_updated` pulse. */
1603
1859
  export type LiveSportsScoreEntry = {
1604
1860
  /** Team name, ordered for the league (away first where the league reads that way). */
@@ -1666,8 +1922,12 @@ export type MarketFlow = {
1666
1922
  direction: "YES" | "NO";
1667
1923
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
1668
1924
  token_id: string | null;
1669
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
1925
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1670
1926
  large_trade_count: number;
1927
+ /**
1928
+ * Deprecated spelling of large_trade_count, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_count.
1929
+ * @deprecated
1930
+ */
1671
1931
  whale_trade_count: number;
1672
1932
  buy_volume_usd: number;
1673
1933
  sell_volume_usd: number;
@@ -1675,7 +1935,7 @@ export type MarketFlow = {
1675
1935
  id: string;
1676
1936
  address: string;
1677
1937
  username: string | null;
1678
- grade: string | null;
1938
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
1679
1939
  side: "YES" | "NO";
1680
1940
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
1681
1941
  token_id: string | null;
@@ -1685,7 +1945,7 @@ export type MarketFlow = {
1685
1945
  oldest_snapshot_as_of: string | null;
1686
1946
  };
1687
1947
  /**
1688
- * Deprecated alias of sharp_money; byte-identical and retained for backward compatibility.
1948
+ * Deprecated alias of sharp_money; byte-identical. Sunset 2027-02-01 (#29352): removed from V1 on that date; read sharp_money.
1689
1949
  * @deprecated
1690
1950
  */
1691
1951
  smart_money: {
@@ -1693,8 +1953,12 @@ export type MarketFlow = {
1693
1953
  direction: "YES" | "NO";
1694
1954
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
1695
1955
  token_id: string | null;
1696
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
1956
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
1697
1957
  large_trade_count: number;
1958
+ /**
1959
+ * Deprecated spelling of large_trade_count, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_count.
1960
+ * @deprecated
1961
+ */
1698
1962
  whale_trade_count: number;
1699
1963
  buy_volume_usd: number;
1700
1964
  sell_volume_usd: number;
@@ -1702,7 +1966,7 @@ export type MarketFlow = {
1702
1966
  id: string;
1703
1967
  address: string;
1704
1968
  username: string | null;
1705
- grade: string | null;
1969
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
1706
1970
  side: "YES" | "NO";
1707
1971
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
1708
1972
  token_id: string | null;
@@ -1736,23 +2000,23 @@ export type MarketHolder = {
1736
2000
  other_outcome_shares?: number;
1737
2001
  /** The wallet's last recorded trade anywhere, null when unknown. */
1738
2002
  last_traded_at: string | null;
1739
- /** This wallet's win rate in the market's canonical category (`market.category`): the share of its resolved markets in that category whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`. The same read `GET /api/v1/trader/{address}/categories` serves per wallet. */
2003
+ /** This wallet's win rate in the market's canonical category (`market.category`): the share of its settled markets in that category (it closed its position by selling out, or the market resolved) whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`. The same read `GET /api/v1/trader/{address}/categories` serves per wallet. */
1740
2004
  category_win_rate?: number;
1741
- /** The two counts `category_win_rate` is the ratio of, from the same row: `wins / decided` equals the rate. Every resolved Polymarket market the wallet traded in the market's canonical category, at any position size, rebuilt daily. Present only with `category_win_rate_status` = `measured`. */
2005
+ /** The two counts `category_win_rate` is the ratio of, from the same row: `wins / decided` equals the rate. Every settled Polymarket market the wallet traded (it closed its position by selling out, or the market resolved) in the market's canonical category, at any position size, rebuilt daily. Present only with `category_win_rate_status` = `measured`. */
1742
2006
  category_win_record?: {
1743
- /** Resolved markets in the category that this wallet closed with a profit. */
2007
+ /** Settled markets in the category that this wallet closed with a profit. */
1744
2008
  wins: number;
1745
- /** Resolved markets in the category that this wallet closed with a profit or a loss. A market resolved at zero realized P&L is in neither count. */
2009
+ /** Settled markets in the category that this wallet closed with a profit or a loss. A market resolved at zero realized P&L is in neither count. */
1746
2010
  decided: number;
1747
2011
  };
1748
- /** The wallet's average entry price in the market's canonical category, as a 0..1 fraction of $1 (0.98 is 98 cents). Its sample is the wallet's settled markets in that category of $20 or more where it bought one side at a known price, so it can differ from the `category_win_record` sample. A wallet that buys near-certain outcomes wins almost every time, so read the win rate beside this price. Present only with `category_win_rate_status` = `measured`, and only when that sample has at least 5 markets. When `category_win_rate_game` is present the price is still the `Esports` category's: there is no per-game price. Absent otherwise and on payloads predating the field. */
2012
+ /** The wallet's average entry price in the market's canonical category, as a 0..1 fraction of $1 (0.98 is 98 cents). Its sample is the wallet's markets in that category that resolved to a winning side, of $20 or more where it bought one side at a known price, so it can differ from the `category_win_record` sample. A wallet that buys near-certain outcomes wins almost every time, so read the win rate beside this price. Present only with `category_win_rate_status` = `measured`, and only when that sample has at least 5 markets. When `category_win_rate_game` is present the price is still the whole `category` bucket's: this field has no per-game or per-league price. Absent otherwise and on payloads predating the field. */
1749
2013
  category_avg_price?: number;
1750
- /** For an esports market, the game `category_win_rate` and `category_win_record` were measured in: `LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`. Present only when the wallet's record in that game clears the 5-resolved-market floor, in which case the rate and record are the game's rather than the `Esports` bucket's. Absent when the rate is the bucket's (the wallet's game history is under the floor), on every non-esports market, and beside every non-measured status. Label the rate with this when present and with the market's `category` otherwise. */
2014
+ /** Where `category_win_rate` and `category_win_record` were measured: for an esports market the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a market in a registered league that league, by the name Pick of the Day uses for it (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other market, and beside every non-measured status. Label the rate with this when present and with the market's `category` otherwise. */
1751
2015
  category_win_rate_game?: string;
1752
2016
  /** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (under the floor of 5 decided markets in the category), or `unavailable` (the market has no canonical category, or the read failed; retry later). Always present on this route. */
1753
2017
  category_win_rate_status: "measured" | "not_enough_data" | "unavailable";
1754
2018
  category_evidence?: HolderCategoryEvidence;
1755
- /** Days since this wallet's first trade. The five badge fields are present together, only for a wallet that draws at least one badge. */
2019
+ /** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request. The five badge fields are present together, only for a wallet that draws at least one badge. */
1756
2020
  wallet_age_days?: number | null;
1757
2021
  /** True when the wallet's first trade was under 30 days ago. */
1758
2022
  is_new_wallet?: boolean;
@@ -1795,6 +2059,15 @@ export type MarketHoldersSideGrades = {
1795
2059
  a: number;
1796
2060
  b: number;
1797
2061
  };
2062
+ /** Polymarket currentValue in USD per grade on one side, over the same wallets as that side's usd total. Each value is rounded to the cent after summing, so s + a + b can differ from the side total by up to 2 cents. */
2063
+ export type MarketHoldersSideGradeUsd = {
2064
+ /** USD held by S-grade wallets netting this side. */
2065
+ s: number;
2066
+ /** USD held by A-grade wallets netting this side. */
2067
+ a: number;
2068
+ /** USD held by B-grade wallets netting this side. */
2069
+ b: number;
2070
+ };
1798
2071
  /** Roster totals BEFORE any `outcome` or `min_grade` filter, so a page always knows the whole market it was cut from. */
1799
2072
  export type MarketHoldersTotals = {
1800
2073
  /** Distinct graded wallets with net exposure; a two-sided wallet counts once. */
@@ -1809,6 +2082,10 @@ export type MarketHoldersTotals = {
1809
2082
  no_usd: number;
1810
2083
  yes_grades: MarketHoldersSideGrades;
1811
2084
  no_grades: MarketHoldersSideGrades;
2085
+ /** yes_usd split by grade: where the S, A and B money on YES sits. */
2086
+ yes_grade_usd: MarketHoldersSideGradeUsd;
2087
+ /** no_usd split by grade: where the S, A and B money on NO sits. */
2088
+ no_grade_usd: MarketHoldersSideGradeUsd;
1812
2089
  };
1813
2090
  export type MarketSearchResult = {
1814
2091
  id: string;
@@ -1820,6 +2097,7 @@ export type MarketSearchResult = {
1820
2097
  platform: "polymarket" | null;
1821
2098
  /** closed once Polymarket has closed trading or the market has resolved; active otherwise. The same rule labels a market on markets/search, markets/explore and market/{condition_id}/snapshot. */
1822
2099
  status: "active" | "closed";
2100
+ event_slug?: string;
1823
2101
  };
1824
2102
  export type MarketSnapshot = {
1825
2103
  market: {
@@ -1838,12 +2116,12 @@ export type MarketSnapshot = {
1838
2116
  /** Polymarket series slug from the canonical identity row, null when unavailable. A sports series identifies a league and must not be used as a per-matchup grouping key. */
1839
2117
  series_slug: string | null;
1840
2118
  /**
1841
- * Always null. Deprecated (#24169): 0xinsider has never stored a value for this field. The key stays on the wire so existing clients keep parsing; do not read it.
2119
+ * Always null. Deprecated (#24169): 0xinsider has never stored a value for this field. The key stays on the wire until its sunset on 2027-02-01 (#29352), when it is removed; do not read it.
1842
2120
  * @deprecated
1843
2121
  */
1844
2122
  market_type: string | null;
1845
2123
  /**
1846
- * Always null. Deprecated (#24169): 0xinsider stores no value for this field on a Polymarket market. The key stays on the wire so existing clients keep parsing; do not read it. market.status and market.resolved_at say whether the market has closed or resolved.
2124
+ * Always null. Deprecated (#24169): 0xinsider stores no value for this field on a Polymarket market. The key stays on the wire until its sunset on 2027-02-01 (#29352), when it is removed; do not read it. market.status and market.resolved_at say whether the market has closed or resolved.
1847
2125
  * @deprecated
1848
2126
  */
1849
2127
  market_result: string | null;
@@ -1914,9 +2192,147 @@ export type MarketSnapshotTrust = {
1914
2192
  current_price: TrustMetadata;
1915
2193
  spread_bps: TrustMetadata;
1916
2194
  };
2195
+ export type MarketTopHolder = {
2196
+ /** 1-based position on this outcome, by shares. */
2197
+ rank: number;
2198
+ /** `trd_`-prefixed trader id, accepted by `GET /api/v1/trader/{address}`. */
2199
+ trader_id: string;
2200
+ /** Lowercased proxy wallet. */
2201
+ address: string;
2202
+ /** The wallet's display name; null when it shows none. */
2203
+ name: string | null;
2204
+ /** All-time trader grade, S to F. Null for a wallet 0xinsider has not graded: this route lists every holder whatever its grade. */
2205
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
2206
+ /** Shares held on this outcome. */
2207
+ shares: number;
2208
+ /** Polymarket's current value of this position, in USD. Null when the provider served none. */
2209
+ current_value_usd: number | null;
2210
+ /** Average price paid for the shares still held, as a 0..1 fraction of $1. Null when the provider served none. */
2211
+ avg_entry_price: number | null;
2212
+ /** Shares on the other outcome when the wallet holds both; the wallet is then listed on both sides. Absent when it is one-sided. */
2213
+ other_outcome_shares?: number;
2214
+ /** Polymarket's realized P&L of this position (sells and redemptions), in USD. Null when the provider served no economics for the row. */
2215
+ position_realized_pnl: number | null;
2216
+ /** Polymarket's mark-to-market P&L of the shares still held, in USD. On a resolved market the mark is the settlement price. */
2217
+ position_unrealized_pnl: number | null;
2218
+ /** `position_realized_pnl` plus `position_unrealized_pnl`, in USD. */
2219
+ position_total_pnl: number | null;
2220
+ /** The wallet's realized P&L on sports and esports markets, in USD, the figure on its 0xinsider profile. Null until 0xinsider has computed the record, never 0 in its place, and null for every row when `profiles_status` is `unavailable`. */
2221
+ in_scope_realized_pnl: number | null;
2222
+ /** The wallet's volume traded on sports and esports markets, in USD. Null under the same rule as `in_scope_realized_pnl`. */
2223
+ in_scope_volume: number | null;
2224
+ /** The wallet's stored trading-style label (see Wallet trading styles); null when it has none. */
2225
+ strategy_type: string | null;
2226
+ /** The wallet's last recorded trade anywhere, null when unknown. */
2227
+ last_traded_at: string | null;
2228
+ /** This wallet's win rate in the market's canonical category (`market.category`): the share of its settled markets in that category (it closed its position by selling out, or the market resolved) whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`. The same read `GET /api/v1/trader/{address}/categories` serves per wallet. */
2229
+ category_win_rate?: number;
2230
+ /** The two counts `category_win_rate` is the ratio of, from the same row: `wins / decided` equals the rate. Every settled Polymarket market the wallet traded (it closed its position by selling out, or the market resolved) in the market's canonical category, at any position size, rebuilt daily. Present only with `category_win_rate_status` = `measured`. */
2231
+ category_win_record?: {
2232
+ /** Settled markets in the category that this wallet closed with a profit. */
2233
+ wins: number;
2234
+ /** Settled markets in the category that this wallet closed with a profit or a loss. A market resolved at zero realized P&L is in neither count. */
2235
+ decided: number;
2236
+ };
2237
+ /** The wallet's average entry price in the market's canonical category, as a 0..1 fraction of $1 (0.98 is 98 cents). Its sample is the wallet's markets in that category that resolved to a winning side, of $20 or more where it bought one side at a known price, so it can differ from the `category_win_record` sample. A wallet that buys near-certain outcomes wins almost every time, so read the win rate beside this price. Present only with `category_win_rate_status` = `measured`, and only when that sample has at least 5 markets. When `category_win_rate_game` is present the price is still the whole `category` bucket's: this field has no per-game or per-league price. Absent otherwise and on payloads predating the field. */
2238
+ category_avg_price?: number;
2239
+ /** Where `category_win_rate` and `category_win_record` were measured: for an esports market the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a market in a registered league that league, by the name Pick of the Day uses for it (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other market, and beside every non-measured status. Label the rate with this when present and with the market's `category` otherwise. */
2240
+ category_win_rate_game?: string;
2241
+ /** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (under the floor of 5 decided markets in the category), or `unavailable` (the read failed; retry later). Absent when the market has no canonical category. */
2242
+ category_win_rate_status?: "measured" | "not_enough_data" | "unavailable";
2243
+ /** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request. The five badge fields are present together, only for a wallet that draws at least one badge. */
2244
+ wallet_age_days?: number | null;
2245
+ /** True when the wallet's first trade was under 30 days ago. */
2246
+ is_new_wallet?: boolean;
2247
+ /** Distinct markets the wallet has traded. */
2248
+ markets_traded?: number | null;
2249
+ /** True when the wallet is flagged as automated. */
2250
+ is_bot?: boolean;
2251
+ /** The wallet's X handle without the @, when linked. */
2252
+ x_username?: string | null;
2253
+ };
2254
+ export type MarketTopHolders = {
2255
+ market: MarketHoldersMarket;
2256
+ /** The largest YES holders, by shares, up to `limit`. */
2257
+ yes: MarketTopHolder[];
2258
+ /** The largest NO holders, by shares, up to `limit`. */
2259
+ no: MarketTopHolder[];
2260
+ totals: MarketTopHoldersTotals;
2261
+ /** `unavailable` when the wallet record read failed: `in_scope_realized_pnl`, `in_scope_volume` and `strategy_type` are then null for every row because they were not read, not because they are unknown. */
2262
+ profiles_status: "available" | "unavailable";
2263
+ /** When the daily pass behind the rows' category win records began. Absent when the market has no category or the read answered no row. */
2264
+ category_records_as_of?: string;
2265
+ /** When this holder sample was built. */
2266
+ computed_at?: string;
2267
+ /** When Polymarket's holder board behind this sample was fetched: up to 120 s before `computed_at` on an open market. Absent on a resolved market, whose sample reads no live board, and when the fetch stamp could not be read. */
2268
+ positions_as_of?: string;
2269
+ };
2270
+ export type MarketTopHoldersTotals = {
2271
+ /** Holders in the YES sample, before `limit`. Equal to `sample_cap` means that many or more. */
2272
+ yes_count: number;
2273
+ /** Holders in the NO sample, before `limit`. */
2274
+ no_count: number;
2275
+ /** Shares summed over the YES sample. */
2276
+ yes_shares: number;
2277
+ /** Shares summed over the NO sample. */
2278
+ no_shares: number;
2279
+ /** The most holders the sample keeps per outcome (100). */
2280
+ sample_cap: number;
2281
+ };
2282
+ /** One market's net buyers and net sellers over a 24h or 7d window, as the market page's wallets in/out panel shows a Pro viewer. */
2283
+ export type MarketWalletsInOut = {
2284
+ /** The market's raw provider condition id. */
2285
+ condition_id: string;
2286
+ /** The window the nets are summed over: 24h or 7d. */
2287
+ window: string;
2288
+ /** The window's inclusive start; null only when the bounds are unknown. */
2289
+ window_start: string | null;
2290
+ /** The window's inclusive end, the read's clock; null only when the bounds are unknown. */
2291
+ window_end: string | null;
2292
+ /** Totals over every wallet that traded the market in the window, not only the listed 50. */
2293
+ summary: {
2294
+ /** Wallets with a positive net in the window. */
2295
+ wallets_in: number;
2296
+ /** Wallets with a negative net in the window. */
2297
+ wallets_out: number;
2298
+ /** The sum of every wallet's net, in USD. A fully rotated wallet nets zero and is on neither side. */
2299
+ net_usd: number;
2300
+ };
2301
+ /** Wallets whose net is positive, largest first, at most 25. */
2302
+ net_buyers: ({
2303
+ /** Lowercase proxy wallet. */
2304
+ address: string;
2305
+ /** The name the site shows: the 0xinsider username, else the shortened address. */
2306
+ display_name: string;
2307
+ /** Today's grade; null for an ungraded or untracked wallet. */
2308
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
2309
+ /** Buys minus sells in the window, both outcomes, in USD: the matched notional, fees excluded. */
2310
+ net_usd: number;
2311
+ /** Fills in the window. */
2312
+ trades: number;
2313
+ /** The wallet's newest trade on any market, at or before window_end; null when unknown. */
2314
+ last_traded_at: string | null;
2315
+ })[];
2316
+ /** Wallets whose net is negative, most negative first, at most 25. */
2317
+ net_sellers: ({
2318
+ /** Lowercase proxy wallet. */
2319
+ address: string;
2320
+ /** The name the site shows: the 0xinsider username, else the shortened address. */
2321
+ display_name: string;
2322
+ /** Today's grade; null for an ungraded or untracked wallet. */
2323
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
2324
+ /** Buys minus sells in the window, both outcomes, in USD: the matched notional, fees excluded. */
2325
+ net_usd: number;
2326
+ /** Fills in the window. */
2327
+ trades: number;
2328
+ /** The wallet's newest trade on any market, at or before window_end; null when unknown. */
2329
+ last_traded_at: string | null;
2330
+ })[];
2331
+ };
1917
2332
  export type McpJsonRpcError = {
1918
2333
  jsonrpc: "2.0";
1919
- id: string | number | null;
2334
+ /** The request's id, or null when the request could not be parsed. Omitted on the answer to an unsolicited response message. */
2335
+ id?: string | number | null;
1920
2336
  error: {
1921
2337
  code: number;
1922
2338
  message: string;
@@ -1945,22 +2361,22 @@ export type PickHolder = {
1945
2361
  shares: number;
1946
2362
  /** USD entry value of this wallet's position: `shares` times the pick's frozen `backed_price`. An entry valuation, never a live balance or the provider's current value. Omitted when the holder snapshot has no valid price. */
1947
2363
  entry_value_usd?: number;
1948
- /** This wallet's win rate in the pick's canonical category bucket (the pick's `category` field, e.g. Basketball -- label the rate with it, never with the narrower `display_category` league, except when `category_win_rate_game` is present, in which case the rate is that game's and is labelled with it): the share of the wallet's resolved markets in that category whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`, on `display_holders` entries, and only when the wallet clears the resolved-market floor; recomputed at serve time from the current category read model, not frozen with the pick. Absent on `holders` entries, legacy rows, and payloads predating the field. */
2364
+ /** This wallet's win rate in the pick's canonical category bucket (the pick's `category` field, e.g. Basketball -- label the rate with it, never with the narrower `display_category` league, except when `category_win_rate_game` is present, in which case the rate is that game's or league's and is labelled with it): the share of the wallet's settled markets in that category (it closed its position by selling out, or the market resolved) whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`, on `display_holders` entries, and only when the wallet clears the settled-market floor; recomputed at serve time from the current category read model, not frozen with the pick. Absent on `holders` entries, legacy rows, and payloads predating the field. */
1949
2365
  category_win_rate?: number;
1950
- /** The two counts `category_win_rate` is the ratio of, read from the same row: `wins / decided` equals the rate. Counts every resolved Polymarket market the wallet traded in the pick's canonical category (or in its game, when `category_win_rate_game` is present), at any position size; the counts are rebuilt daily. Present only with `category_win_rate_status` = `measured`; absent otherwise and on payloads predating the field. */
2366
+ /** The two counts `category_win_rate` is the ratio of, read from the same row: `wins / decided` equals the rate. Counts every settled Polymarket market the wallet traded (it closed its position by selling out, or the market resolved) in the pick's canonical category (or in its game or league, when `category_win_rate_game` is present), at any position size; the counts are rebuilt daily. Present only with `category_win_rate_status` = `measured`; absent otherwise and on payloads predating the field. */
1951
2367
  category_win_record?: {
1952
- /** Resolved markets in the category that this wallet closed with a profit. */
2368
+ /** Settled markets in the category that this wallet closed with a profit. */
1953
2369
  wins: number;
1954
- /** Resolved markets in the category that this wallet closed with a profit or a loss. A market resolved at zero realized P&L is in neither count. */
2370
+ /** Settled markets in the category that this wallet closed with a profit or a loss. A market resolved at zero realized P&L is in neither count. */
1955
2371
  decided: number;
1956
2372
  };
1957
- /** The wallet's average entry price in the pick's canonical category, as a 0..1 fraction of $1 (0.98 is 98 cents). Its sample is the wallet's settled markets in that category of $20 or more where it bought one side at a known price, so it can differ from the `category_win_record` sample. A wallet that buys near-certain outcomes wins almost every time, so read the win rate beside this price. Present only with `category_win_rate_status` = `measured`, and only when that sample has at least 5 markets. When `category_win_rate_game` is present the price is still the `Esports` category's: there is no per-game price. Absent otherwise and on payloads predating the field. */
2373
+ /** The wallet's average entry price in the pick's canonical category, as a 0..1 fraction of $1 (0.98 is 98 cents). Its sample is the wallet's markets in that category that resolved to a winning side, of $20 or more where it bought one side at a known price, so it can differ from the `category_win_record` sample. A wallet that buys near-certain outcomes wins almost every time, so read the win rate beside this price. Present only with `category_win_rate_status` = `measured`, and only when that sample has at least 5 markets. When `category_win_rate_game` is present the price is still the whole `category` bucket's: this field has no per-game or per-league price. Absent otherwise and on payloads predating the field. */
1958
2374
  category_avg_price?: number;
1959
- /** For an esports pick, the game `category_win_rate` and `category_win_record` were measured in, by the same name the pick's `display_category` uses for it: `LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`. Present only when the wallet's record in that game clears the 5-resolved-market floor, in which case the rate and record are the game's rather than the `Esports` bucket's. Absent when the rate is the bucket's (the wallet's game history is under the floor), on every non-esports pick, beside every non-measured status, and on payloads predating the field. Label the rate with this when present and with `category` otherwise. */
2375
+ /** Where `category_win_rate` and `category_win_record` were measured, by the same name the pick's `display_category` uses for it: for an esports pick the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a pick in a registered league that league (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other pick, beside every non-measured status, and on payloads predating the field. Label the rate with this when present and with `category` otherwise. */
1960
2376
  category_win_rate_game?: string;
1961
- /** Why `category_win_rate` is present or absent on a `display_holders` entry: `measured` (rate present), `not_enough_data` (the wallet is below the resolved-market floor of 5 in the category), or `unavailable` (the annotation read failed; retry later). Absent entirely on `holders` entries, legacy rows, and payloads predating the field -- absence means the roster was never annotated, not a small sample. */
2377
+ /** Why `category_win_rate` is present or absent on a `display_holders` entry: `measured` (rate present), `not_enough_data` (the wallet is below the settled-market floor of 5 in the category), or `unavailable` (the annotation read failed; retry later). Absent entirely on `holders` entries, legacy rows, and payloads predating the field -- absence means the roster was never annotated, not a small sample. */
1962
2378
  category_win_rate_status?: "measured" | "not_enough_data" | "unavailable";
1963
- /** Days since this wallet's first trade. Stamped at serve time from the wallet's current trader record, never frozen with the pick. The five badge fields are present together, and only for a wallet that carries at least one badge; all absent means no badge, or a body cached before the fields shipped. */
2379
+ /** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request, and the pick's ETag holds between requests. Stamped at serve time from the wallet's current trader record, never frozen with the pick. The five badge fields are present together, and only for a wallet that carries at least one badge; all absent means no badge, or a body cached before the fields shipped. */
1964
2380
  wallet_age_days?: number | null;
1965
2381
  /** True when the wallet's first trade was under 30 days ago. Stamped at serve time from the wallet's current trader record, never frozen with the pick. The five badge fields are present together, and only for a wallet that carries at least one badge; all absent means no badge, or a body cached before the fields shipped. */
1966
2382
  is_new_wallet?: boolean;
@@ -2106,9 +2522,9 @@ export type PickOfTheDay = {
2106
2522
  grade: string | null;
2107
2523
  /** The canonical sport bucket the win rate was measured over (for example Basketball). Can be BROADER than the pick's display_category, which names an exact league such as NBA — label the rate with this field, never with display_category. */
2108
2524
  canonical_category: string;
2109
- /** Share of the trader’s resolved markets in canonical_category with positive realized P&L, as a 0..1 fraction. Null when not measured. This is a trader statistic, not the pick’s probability of winning. */
2525
+ /** Share of the trader’s settled markets in canonical_category (closed by selling out, or resolved) with positive realized P&L, as a 0..1 fraction. Null when not measured. This is a trader statistic, not the pick’s probability of winning. */
2110
2526
  win_rate: number | null;
2111
- /** Number of resolved markets behind win_rate; null when not measured. */
2527
+ /** Number of settled markets behind win_rate; null when not measured. */
2112
2528
  n_resolved: number | null;
2113
2529
  /** Recorded Polymarket position value on the backed outcome, in USD. It can change after this snapshot. */
2114
2530
  position_usd: number;
@@ -2429,7 +2845,7 @@ export type PickOfTheDayLedgerOpenedEntry = {
2429
2845
  matchup: string;
2430
2846
  /** Frozen canonical sport bucket (for example Basketball or MMA), not the exact public league identity; the archive owns that. */
2431
2847
  category: string;
2432
- /** The pick's public page. */
2848
+ /** The pick's stable public page, `https://0xinsider.com/pick-of-the-day/picks/{pick_id}`. */
2433
2849
  permalink: string;
2434
2850
  /** Stable pick row identity as decimal text. Never use a quality rank as identity. */
2435
2851
  pick_id: string;
@@ -2461,7 +2877,7 @@ export type PickOfTheDayLedgerSealedEntry = {
2461
2877
  commitment_algo: "sha256(canonical_json(payload)||nonce)";
2462
2878
  /** When the hash was frozen. Always strictly before kickoff: a pick that reaches kickoff unsealed stays unsealed forever, because a seal written after the game started would be a backdated proof. */
2463
2879
  sealed_at: string;
2464
- /** The pick's public page. */
2880
+ /** The pick's stable public page, `https://0xinsider.com/pick-of-the-day/picks/{pick_id}`. */
2465
2881
  permalink: string;
2466
2882
  /** Stable pick row identity as decimal text. Never use a quality rank as identity. */
2467
2883
  pick_id: string;
@@ -2501,7 +2917,7 @@ export type PickOfTheDayLedgerUncommittedEntry = {
2501
2917
  resolved_at: string | null;
2502
2918
  /** The pick's market, side and price once it has settled; null while it is pending, and null for a settled pick whose stored row lacks one of these columns. Not hashed: nothing was committed over these values, which is what pre_commitment: true says. */
2503
2919
  payload: PickOfTheDayUncommittedPayload | null;
2504
- /** The pick's public page. */
2920
+ /** The pick's stable public page, `https://0xinsider.com/pick-of-the-day/picks/{pick_id}`. */
2505
2921
  permalink: string;
2506
2922
  /** Stable pick row identity as decimal text. Never use a quality rank as identity. */
2507
2923
  pick_id: string;
@@ -2534,14 +2950,411 @@ export type PickOfTheDayNoEntitledPicks = {
2534
2950
  message: string;
2535
2951
  /** Rank-ordered entitled selections that have not released. Every row retains release_at and kickoff; unauthorized scheduled ranks appear only in identity-free locked_picks. */
2536
2952
  scheduled_picks?: ScheduledPickSlot[];
2537
- /** Entitled published picks whose holder proof is unreadable, ordered by rank. Unauthorized ranks appear only in locked_picks and cannot trigger proof warming. Read retry_at for the next read. */
2538
- proof_pending_picks?: ProofPendingPickSlot[];
2539
2953
  /**
2540
2954
  * Deprecated (#24157): always null. No replacement lineage was ever recorded in this field; the key stays so existing V1 clients keep parsing. Identify a pick by pick_id.
2541
2955
  * @deprecated
2542
2956
  */
2543
2957
  supersedes_pick_id: string | null;
2544
2958
  };
2959
+ export type PickOfTheDayStats = {
2960
+ categories: {
2961
+ canonical_category?: string;
2962
+ clv_avg_display?: string;
2963
+ clv_avg_pct?: number;
2964
+ clv_avg_pp?: number;
2965
+ clv_avg_pp_display?: string;
2966
+ clv_measured: number;
2967
+ edge_display?: string;
2968
+ edge_pp?: number;
2969
+ key: string;
2970
+ label: string;
2971
+ losses: number;
2972
+ net_profit_display?: string;
2973
+ net_profit_usd?: number;
2974
+ pending: number;
2975
+ picks: number;
2976
+ priced_decided: number;
2977
+ priced_in_display?: string;
2978
+ priced_in_pct?: number;
2979
+ roi_display?: string;
2980
+ roi_pct?: number;
2981
+ settled: number;
2982
+ small_sample: boolean;
2983
+ staked_usd: number;
2984
+ unit_score?: number;
2985
+ unit_score_display?: string;
2986
+ void: number;
2987
+ win_rate_display?: string;
2988
+ win_rate_pct?: number;
2989
+ wins: number;
2990
+ }[];
2991
+ days: ({
2992
+ date: string;
2993
+ losses: number;
2994
+ net_profit_display?: string;
2995
+ net_profit_usd?: number;
2996
+ pending: number;
2997
+ picks: number;
2998
+ sweep?: "win" | "loss";
2999
+ unit_score?: number;
3000
+ unit_score_display?: string;
3001
+ void: number;
3002
+ wins: number;
3003
+ })[];
3004
+ hit_rate: PickOfTheDayHitRate;
3005
+ market_expectations: {
3006
+ as_of_date: string;
3007
+ price_basis: string;
3008
+ timezone: string;
3009
+ windows: ({
3010
+ clv_avg_display: string | null;
3011
+ clv_avg_pct: number | null;
3012
+ clv_avg_pp: number | null;
3013
+ clv_avg_pp_display: string | null;
3014
+ clv_measured: number;
3015
+ clv_missing: number;
3016
+ expected_wins: number | null;
3017
+ expected_wins_display: string | null;
3018
+ from_date: string | null;
3019
+ key: string;
3020
+ label: string;
3021
+ numeric_unavailable: boolean;
3022
+ priced_decided: number;
3023
+ through_date: string;
3024
+ units: number | null;
3025
+ units_display: string | null;
3026
+ units_z: number | null;
3027
+ units_z_display: string | null;
3028
+ unpriced_decided: number;
3029
+ wins: number;
3030
+ wins_z: number | null;
3031
+ wins_z_display: string | null;
3032
+ })[];
3033
+ };
3034
+ market_types: {
3035
+ canonical_category?: string;
3036
+ clv_avg_display?: string;
3037
+ clv_avg_pct?: number;
3038
+ clv_avg_pp?: number;
3039
+ clv_avg_pp_display?: string;
3040
+ clv_measured: number;
3041
+ edge_display?: string;
3042
+ edge_pp?: number;
3043
+ key: string;
3044
+ label: string;
3045
+ losses: number;
3046
+ net_profit_display?: string;
3047
+ net_profit_usd?: number;
3048
+ pending: number;
3049
+ picks: number;
3050
+ priced_decided: number;
3051
+ priced_in_display?: string;
3052
+ priced_in_pct?: number;
3053
+ roi_display?: string;
3054
+ roi_pct?: number;
3055
+ settled: number;
3056
+ small_sample: boolean;
3057
+ staked_usd: number;
3058
+ unit_score?: number;
3059
+ unit_score_display?: string;
3060
+ void: number;
3061
+ win_rate_display?: string;
3062
+ win_rate_pct?: number;
3063
+ wins: number;
3064
+ }[];
3065
+ months: {
3066
+ canonical_category?: string;
3067
+ clv_avg_display?: string;
3068
+ clv_avg_pct?: number;
3069
+ clv_avg_pp?: number;
3070
+ clv_avg_pp_display?: string;
3071
+ clv_measured: number;
3072
+ edge_display?: string;
3073
+ edge_pp?: number;
3074
+ key: string;
3075
+ label: string;
3076
+ losses: number;
3077
+ net_profit_display?: string;
3078
+ net_profit_usd?: number;
3079
+ pending: number;
3080
+ picks: number;
3081
+ priced_decided: number;
3082
+ priced_in_display?: string;
3083
+ priced_in_pct?: number;
3084
+ roi_display?: string;
3085
+ roi_pct?: number;
3086
+ settled: number;
3087
+ small_sample: boolean;
3088
+ staked_usd: number;
3089
+ unit_score?: number;
3090
+ unit_score_display?: string;
3091
+ void: number;
3092
+ win_rate_display?: string;
3093
+ win_rate_pct?: number;
3094
+ wins: number;
3095
+ }[];
3096
+ outcome_stats: {
3097
+ concentration: {
3098
+ positive_wins: number;
3099
+ remaining_valued_decided: number;
3100
+ removed_wins: number;
3101
+ roi_without_top_wins_display: string | null;
3102
+ roi_without_top_wins_pct: number | null;
3103
+ target_wins: number;
3104
+ top_wins_share_display: string | null;
3105
+ top_wins_share_pct: number | null;
3106
+ valued_decided: number;
3107
+ };
3108
+ drawdown: {
3109
+ completed_days: number;
3110
+ current_days_below_peak: number | null;
3111
+ current_drawdown_display: string | null;
3112
+ current_drawdown_units: number | null;
3113
+ days_below_peak: number | null;
3114
+ excluded_days: number;
3115
+ from_date: string | null;
3116
+ longest_days_below_peak: number | null;
3117
+ longest_recovery_days: number | null;
3118
+ max_drawdown_display: string | null;
3119
+ max_drawdown_units: number | null;
3120
+ peak_date: string | null;
3121
+ peak_net_profit_usd: number | null;
3122
+ through_date: string | null;
3123
+ };
3124
+ profit_factor: {
3125
+ display: string | null;
3126
+ gross_loss_usd: number | null;
3127
+ gross_profit_usd: number | null;
3128
+ state: "empty" | "measured" | "no_losses" | "numeric_unavailable";
3129
+ value: number | null;
3130
+ valued_decided: number;
3131
+ };
3132
+ rolling: ({
3133
+ from_date: string | null;
3134
+ losses: number;
3135
+ roi_display: string | null;
3136
+ roi_pct: number | null;
3137
+ through_date: string | null;
3138
+ units: number | null;
3139
+ units_display: string | null;
3140
+ valued_decided: number;
3141
+ win_rate_display: string | null;
3142
+ win_rate_pct: number | null;
3143
+ window_size: number;
3144
+ wins: number;
3145
+ })[];
3146
+ };
3147
+ price_bands: {
3148
+ canonical_category?: string;
3149
+ clv_avg_display?: string;
3150
+ clv_avg_pct?: number;
3151
+ clv_avg_pp?: number;
3152
+ clv_avg_pp_display?: string;
3153
+ clv_measured: number;
3154
+ edge_display?: string;
3155
+ edge_pp?: number;
3156
+ key: string;
3157
+ label: string;
3158
+ losses: number;
3159
+ net_profit_display?: string;
3160
+ net_profit_usd?: number;
3161
+ pending: number;
3162
+ picks: number;
3163
+ priced_decided: number;
3164
+ priced_in_display?: string;
3165
+ priced_in_pct?: number;
3166
+ roi_display?: string;
3167
+ roi_pct?: number;
3168
+ settled: number;
3169
+ small_sample: boolean;
3170
+ staked_usd: number;
3171
+ unit_score?: number;
3172
+ unit_score_display?: string;
3173
+ void: number;
3174
+ win_rate_display?: string;
3175
+ win_rate_pct?: number;
3176
+ wins: number;
3177
+ }[];
3178
+ records: {
3179
+ best_day?: {
3180
+ date: string;
3181
+ date_display: string;
3182
+ losses: number;
3183
+ net_profit_display: string;
3184
+ net_profit_usd: number;
3185
+ picks: number;
3186
+ wins: number;
3187
+ };
3188
+ biggest_win?: {
3189
+ category: string;
3190
+ date: string;
3191
+ date_display: string;
3192
+ matchup: string;
3193
+ net_profit_display: string;
3194
+ net_profit_usd: number;
3195
+ };
3196
+ longest_losing_day_streak?: {
3197
+ days: number;
3198
+ end_date: string;
3199
+ net_profit_display: string;
3200
+ net_profit_usd: number;
3201
+ range_display: string;
3202
+ start_date: string;
3203
+ };
3204
+ longest_winning_day_streak?: {
3205
+ days: number;
3206
+ end_date: string;
3207
+ net_profit_display: string;
3208
+ net_profit_usd: number;
3209
+ range_display: string;
3210
+ start_date: string;
3211
+ };
3212
+ sweeps: {
3213
+ clean_sweeps: number;
3214
+ latest_clean_sweep?: {
3215
+ date: string;
3216
+ date_display: string;
3217
+ losses: number;
3218
+ wins: number;
3219
+ };
3220
+ latest_wipeout?: {
3221
+ date: string;
3222
+ date_display: string;
3223
+ losses: number;
3224
+ wins: number;
3225
+ };
3226
+ min_decided: number;
3227
+ wipeouts: number;
3228
+ };
3229
+ winning_days?: {
3230
+ flat: number;
3231
+ losing: number;
3232
+ settled: number;
3233
+ winning: number;
3234
+ winning_pct: number;
3235
+ winning_pct_display: string;
3236
+ };
3237
+ worst_day?: {
3238
+ date: string;
3239
+ date_display: string;
3240
+ losses: number;
3241
+ net_profit_display: string;
3242
+ net_profit_usd: number;
3243
+ picks: number;
3244
+ wins: number;
3245
+ };
3246
+ };
3247
+ sports: {
3248
+ canonical_category?: string;
3249
+ clv_avg_display?: string;
3250
+ clv_avg_pct?: number;
3251
+ clv_avg_pp?: number;
3252
+ clv_avg_pp_display?: string;
3253
+ clv_measured: number;
3254
+ edge_display?: string;
3255
+ edge_pp?: number;
3256
+ key: string;
3257
+ label: string;
3258
+ losses: number;
3259
+ net_profit_display?: string;
3260
+ net_profit_usd?: number;
3261
+ pending: number;
3262
+ picks: number;
3263
+ priced_decided: number;
3264
+ priced_in_display?: string;
3265
+ priced_in_pct?: number;
3266
+ roi_display?: string;
3267
+ roi_pct?: number;
3268
+ settled: number;
3269
+ small_sample: boolean;
3270
+ staked_usd: number;
3271
+ unit_score?: number;
3272
+ unit_score_display?: string;
3273
+ void: number;
3274
+ win_rate_display?: string;
3275
+ win_rate_pct?: number;
3276
+ wins: number;
3277
+ }[];
3278
+ streaks: {
3279
+ current?: number;
3280
+ current_day?: number;
3281
+ current_day_display?: string;
3282
+ current_display?: string;
3283
+ longest_loss: number;
3284
+ longest_win: number;
3285
+ };
3286
+ tiers: {
3287
+ canonical_category?: string;
3288
+ clv_avg_display?: string;
3289
+ clv_avg_pct?: number;
3290
+ clv_avg_pp?: number;
3291
+ clv_avg_pp_display?: string;
3292
+ clv_measured: number;
3293
+ edge_display?: string;
3294
+ edge_pp?: number;
3295
+ key: string;
3296
+ label: string;
3297
+ losses: number;
3298
+ net_profit_display?: string;
3299
+ net_profit_usd?: number;
3300
+ pending: number;
3301
+ picks: number;
3302
+ priced_decided: number;
3303
+ priced_in_display?: string;
3304
+ priced_in_pct?: number;
3305
+ roi_display?: string;
3306
+ roi_pct?: number;
3307
+ settled: number;
3308
+ small_sample: boolean;
3309
+ staked_usd: number;
3310
+ unit_score?: number;
3311
+ unit_score_display?: string;
3312
+ void: number;
3313
+ win_rate_display?: string;
3314
+ win_rate_pct?: number;
3315
+ wins: number;
3316
+ }[];
3317
+ total_sides: {
3318
+ canonical_category?: string;
3319
+ clv_avg_display?: string;
3320
+ clv_avg_pct?: number;
3321
+ clv_avg_pp?: number;
3322
+ clv_avg_pp_display?: string;
3323
+ clv_measured: number;
3324
+ edge_display?: string;
3325
+ edge_pp?: number;
3326
+ key: string;
3327
+ label: string;
3328
+ losses: number;
3329
+ net_profit_display?: string;
3330
+ net_profit_usd?: number;
3331
+ pending: number;
3332
+ picks: number;
3333
+ priced_decided: number;
3334
+ priced_in_display?: string;
3335
+ priced_in_pct?: number;
3336
+ roi_display?: string;
3337
+ roi_pct?: number;
3338
+ settled: number;
3339
+ small_sample: boolean;
3340
+ staked_usd: number;
3341
+ unit_score?: number;
3342
+ unit_score_display?: string;
3343
+ void: number;
3344
+ win_rate_display?: string;
3345
+ win_rate_pct?: number;
3346
+ wins: number;
3347
+ }[];
3348
+ voids: {
3349
+ backed_price?: number;
3350
+ backed_side?: string;
3351
+ category?: string;
3352
+ matchup?: string;
3353
+ pick_date: string;
3354
+ pick_id: string;
3355
+ pick_rank: number;
3356
+ }[];
3357
+ };
2545
3358
  /** A settled uncommitted pick's market, side and price. The same eight fields as PickOfTheDayCommitmentPayload, in the same key order, so a settled pick's side and price sit under payload whatever the entry's state. It is NOT a commitment: no hash was taken over it before the game, and it proves nothing about when the pick was made. */
2546
3359
  export type PickOfTheDayUncommittedPayload = {
2547
3360
  /** Frozen pre-game price of the backed side, 0..1, as the plain decimal text of the stored NUMERIC at full stored precision, trailing zeros included -- rendered exactly as the commitment payload renders it. */
@@ -2561,18 +3374,18 @@ export type PickOfTheDayUncommittedPayload = {
2561
3374
  /** Provider platform. Always polymarket. */
2562
3375
  platform: "polymarket";
2563
3376
  };
2564
- /** Provider-first sports context for a Pick of the Day market: team crests, league branding, and live score. Team logos and league logo are provider-owned (Polymarket /teams crests for clubs, country flags for national teams and tennis players); no local derivation. */
3377
+ /** Provider-first sports context for a Pick of the Day market: team crests, league branding, and live score. Each team `logo` is a registered club crest or national flag as a same-origin path where one exists, and provider artwork otherwise. */
2565
3378
  export type PickSportsContext = {
2566
3379
  /** League or competition display name (e.g. "Premier League"). */
2567
3380
  league_name: string | null;
2568
- /** Provider-owned event taxonomy from Gamma eventMetadata, joined in league · serie · tournament order with blanks and case-insensitive duplicates removed. Separate from league_name; omitted when the provider does not supply the metadata. */
3381
+ /** Provider-owned event taxonomy from Gamma eventMetadata, joined in league · serie · tournament order with blanks and case-insensitive duplicates removed. A tennis qualifying match ends in ", Qualification", including an ATP Challenger qualifying match, which Gamma marks only in eventMetadata.tennisFixtureSource. Separate from league_name; omitted when the provider does not supply the metadata. */
2569
3382
  competition_label?: string;
2570
3383
  /** League logo URL (provider-owned). */
2571
3384
  league_logo: string | null;
2572
3385
  /** The team mapped to the market's YES outcome, or the parent-event home/first team when event_matchup is true. */
2573
- yes_team: PickSportsTeam;
3386
+ yes_team: PickSportsTeam | null;
2574
3387
  /** The team mapped to the market's NO outcome, or the parent-event away/second team when event_matchup is true. */
2575
- no_team: PickSportsTeam;
3388
+ no_team: PickSportsTeam | null;
2576
3389
  /** Provider game identifier (Polymarket Gamma gameId); omitted when the provider supplies none. */
2577
3390
  game_id?: number;
2578
3391
  /** Always present. True when the two teams are the parent-event match identity for a teamless binary leg (e.g. a draw, totals, or prop market), not the market's own outcomes. */
@@ -2588,11 +3401,11 @@ export type PickSportsTeam = {
2588
3401
  label: string | null;
2589
3402
  /** Abbreviated team label (e.g. "POR"). */
2590
3403
  short_label: string | null;
2591
- /** Full team or competitor name (e.g. "Portugal national football team"). */
3404
+ /** The name to show for this team or competitor, the same on every surface (e.g. "UCF Knights", "Oklahoma City Thunder", "Portugal"). `label` keeps the market outcome's own spelling. */
2592
3405
  full_name: string | null;
2593
3406
  /** Provider team identifier (Polymarket /teams id). */
2594
3407
  provider_id: number | null;
2595
- /** Team crest or flag URL. Official NFL (32), WNBA (15), NBA (30), NHL (32), and MLB (30) club crests use same-origin relative paths (`/api/sports/team-logos/{league}/{abbr}.svg?v=<content hash>`); resolve relative URLs against the API origin. Vendored soccer club crests use the same path with `.png`. Other teams use provider artwork, including country flags for national teams and tennis players. Novelty and national-team rows outside the vendored club sets retain provider artwork. */
3408
+ /** Team crest or flag URL. Official NFL (32), WNBA (15), NBA (30), NHL (32), and MLB (30) club crests use same-origin relative paths (`/api/sports/team-logos/{league}/{abbr}.svg?v=<content hash>`); resolve relative URLs against the API origin. Vendored soccer club crests use the same path with `.png`. National teams in the registered national-team competitions use the same path with `.svg`: the official national flag, drawn whole at its own aspect. Other teams use provider artwork, including country flags for tennis players. Novelty rows, and national-team rows that are not exactly one country, retain provider artwork. */
2596
3409
  logo: string | null;
2597
3410
  /** True when artwork measurements show that the team mark needs a light plate on a dark background. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured by the teams sync. Always sent; false when no current measurement marks the logo dark. */
2598
3411
  logo_mark_dark: boolean;
@@ -2615,16 +3428,28 @@ export type PickSportsTeam = {
2615
3428
  headshot_revision?: number;
2616
3429
  /** Optional latest retrieved ATP/WTA singles rank for this player. Absent for unranked, ambiguous, doubles, expired, or unavailable identities. This is not rank at match time. */
2617
3430
  ranking?: TennisRanking;
3431
+ /** True when artwork measurements show that the team mark disappears on a white background and needs a dark plate there: the light-background twin of logo_mark_dark. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured on white by the teams sync. Always sent; false when no current measurement marks the logo light. */
3432
+ logo_mark_light: boolean;
3433
+ /** True when logo_mark_dark and logo_mark_light are both measurements of this exact logo URL, so their false means the mark is legible on that background. Every vendored crest is measured; a provider logo is measured once the teams sync has scored it, usually within a few hourly cycles of first appearing. Always sent; false while the logo is not measured yet. */
3434
+ logo_mark_measured: boolean;
2618
3435
  };
2619
3436
  export type PlatformCapabilities = {
2620
3437
  grade: PlatformCapabilityStatus;
2621
3438
  pnl: PlatformCapabilityStatus;
2622
3439
  strategy: PlatformCapabilityStatus;
2623
3440
  timeline: PlatformCapabilityStatus;
2624
- /** The large-trade feed. Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value. */
3441
+ /** The large-trade feed. Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
2625
3442
  large_trades: PlatformCapabilityStatus;
3443
+ /**
3444
+ * Deprecated spelling of large_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trades.
3445
+ * @deprecated
3446
+ */
2626
3447
  whale_signal: PlatformCapabilityStatus;
2627
3448
  suspicious_trades: PlatformCapabilityStatus;
3449
+ /**
3450
+ * Deprecated spelling of suspicious_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read suspicious_trades.
3451
+ * @deprecated
3452
+ */
2628
3453
  insider_radar: PlatformCapabilityStatus;
2629
3454
  market_snapshot: PlatformCapabilityStatus;
2630
3455
  };
@@ -2635,15 +3460,15 @@ export type Platforms = {
2635
3460
  polymarket: PlatformCapabilities;
2636
3461
  };
2637
3462
  };
2638
- /** A derived 0xinsider correction to Polymarket's P&L, never a Polymarket value. Polymarket misbooks neg-risk conversions, in both directions: it puts cost on placeholder YES outcomes minted by a conversion and never books it as a loss (negative amount), and its position records leave out shares the wallet really got, such as YES minted by a conversion, so it books no P&L on them (positive amount). Per neg-risk market the wallet converted in, 0xinsider measures Polymarket's own activity cash against the sum of its position P&L, and sums the difference over every measured market whose shares did not move by direct transfer: transferred shares have no activity row, so such a market keeps Polymarket's figure and is counted in markets_excluded. It is published once every neg-risk market the wallet converted in is measured and checked for transfers, and stays as last published until then (on the trader body, pnl.correction_pending says so); a sum under $1 either way publishes nothing. The body's own P&L fields keep Polymarket's figures; this object adds the amount and the corrected figures. Money is truncated toward zero to cents. */
3463
+ /** A derived 0xinsider correction to Polymarket's P&L, never a Polymarket value. Polymarket misbooks neg-risk conversions, in both directions: it puts cost on placeholder YES outcomes minted by a conversion and never books it as a loss (negative amount), and its position records leave out shares the wallet really got, such as YES minted by a conversion, so it books no P&L on them (positive amount). Per neg-risk market the wallet converted in, 0xinsider measures Polymarket's own activity cash against the sum of its position P&L, and sums the difference over every measured market whose shares did not move by direct transfer: transferred shares have no activity row, so such a market keeps Polymarket's figure and is counted in markets_excluded. It is published once every neg-risk market with a sports or esports event that the wallet converted in is measured and checked for transfers, and stays as last published until then; a market with no sports or esports event is not measured, and counts only when it was measured before (on the trader body, pnl.correction_pending says so); a sum under $1 either way publishes nothing. The body's own P&L fields keep Polymarket's figures; this object adds the amount and the corrected figures. Money is truncated toward zero to cents. */
2639
3464
  export type PnlCorrection = {
2640
3465
  /** The correction method. */
2641
3466
  basis: "neg_risk_conversion_v1";
2642
3467
  /** The correction in USD. Negative when Polymarket overstates the wallet. */
2643
3468
  amount: number;
2644
- /** Polymarket's net realized P&L plus amount: the figure 0xinsider grades on. Omitted when Polymarket's figure is. */
3469
+ /** Polymarket's net realized P&L plus amount. Since 2026-10-22 the grade reads this figure's sports and esports share. Omitted when Polymarket's figure is. */
2645
3470
  realized?: number;
2646
- /** Polymarket's net total P&L plus amount: the 0xinsider profile's Total P&L. Omitted when Polymarket's figure is, and on leaderboard entries. */
3471
+ /** Polymarket's net total P&L over every Polymarket market of the wallet, plus amount. Omitted when Polymarket's figure is, and on leaderboard entries. */
2647
3472
  net_total?: number;
2648
3473
  /** The newest measurement among the measured markets. */
2649
3474
  as_of: string;
@@ -2686,10 +3511,16 @@ export type Position = {
2686
3511
  address: string;
2687
3512
  username?: string;
2688
3513
  grade?: "S" | "A" | "B" | "C" | "D" | "F";
2689
- /** Win rate as a ratio from 0 to 1 (0.62 means 62%), the same scale as stats.win_rate on GET /api/v1/trader/{address}. Absent when unknown. */
3514
+ /** Sports and esports win rate as a ratio from 0 to 1 (0.62 means 62%): wins over the decided sports and esports markets on the wallet's record, the same figure as pnl.in_scope.win_rate and stats.win_rate on GET /api/v1/trader/{address}. Since 2026-10-27 it no longer counts other markets (#29953). Absent when the wallet has no record or no decided market. */
2690
3515
  win_rate?: number;
2691
- /** Polymarket's net total P&L for the wallet in USD: native Polymarket position P&L across all markets, fees included, plus credited maker and taker rebates (trader_trading_pnl.net_total_pnl). The 0xinsider profile's Total P&L is this figure unless the wallet has a published correction for neg-risk conversions, which GET /api/v1/trader/{address} serves as pnl.correction; the profile then shows pnl.correction.net_total. Not the Polymarket leaderboard figure, which GET /api/v1/trader/{address} still serves as pnl.total. Omitted when the wallet has no native accounting snapshot; the leaderboard figure is never substituted. */
3516
+ /**
3517
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's net total P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29953). Read trader.in_scope_realized_pnl.
3518
+ * @deprecated
3519
+ */
2692
3520
  pnl?: number;
3521
+ /** The wallet's realized P&L in USD on sports and esports markets, the figure the 0xinsider profile shows: the record behind pnl.in_scope.realized_pnl on GET /api/v1/trader/{address}, to cents. For a graded wallet it is read from the latest grading pass, so it can trail that figure until the next pass. Omitted until 0xinsider has computed the wallet's record (#29953). */
3522
+ in_scope_realized_pnl?: number;
3523
+ /** Sports and esports markets on the wallet's record, pnl.in_scope.markets on GET /api/v1/trader/{address}. Since 2026-10-27 it no longer counts other markets (#29953). Absent when the wallet has no record. */
2693
3524
  markets?: number;
2694
3525
  /** Days since the wallet's first-seen time. For a wallet 0xinsider first recorded on or after March 21, 2026, that is when 0xinsider recorded it. For a wallet recorded earlier, it is usually the wallet's first Polymarket activity, so the age can run to years. It is not the wallet's on-chain age or the time of its first trade. Absent when the first-seen time is unknown. */
2695
3526
  wallet_age_days?: number;
@@ -2793,15 +3624,15 @@ export type ProofPendingPickSlot = {
2793
3624
  supersedes_pick_id: string | null;
2794
3625
  };
2795
3626
  export type ReportPayload = {
2796
- /** Canonical key since #16304; total_whale_trades is its deprecated spelling, emitted beside it with the same value. */
3627
+ /** Canonical key since #16304; total_whale_trades is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
2797
3628
  total_large_trades: number | null;
2798
3629
  total_whale_trades: number | null;
2799
- /** Canonical key since #16304; total_whale_volume is its deprecated spelling, emitted beside it with the same value. */
3630
+ /** Canonical key since #16304; total_whale_volume is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
2800
3631
  total_large_trade_volume: number | null;
2801
3632
  total_whale_volume: number | null;
2802
3633
  biggest_trade_size: number | null;
2803
3634
  active_traders: number | null;
2804
- /** Canonical key since #16304; top_whale_trades is its deprecated spelling, emitted beside it with the same value. */
3635
+ /** Canonical key since #16304; top_whale_trades is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
2805
3636
  top_large_trades: ({
2806
3637
  /** Provider outcome label for the traded side. */
2807
3638
  outcome: string | null;
@@ -2828,7 +3659,7 @@ export type ReportPayload = {
2828
3659
  /** Trader pseudonym, when no display name is known. */
2829
3660
  pseudonym: string | null;
2830
3661
  /** Trader grade (S-F) at snapshot time. */
2831
- trader_grade: string | null;
3662
+ trader_grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
2832
3663
  })[] | null;
2833
3664
  top_whale_trades: ({
2834
3665
  /** Provider outcome label for the traded side. */
@@ -2856,11 +3687,19 @@ export type ReportPayload = {
2856
3687
  /** Trader pseudonym, when no display name is known. */
2857
3688
  pseudonym: string | null;
2858
3689
  /** Trader grade (S-F) at snapshot time. */
2859
- trader_grade: string | null;
3690
+ trader_grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
3691
+ })[] | null;
3692
+ categories: ({
3693
+ category: string | null;
3694
+ large_trade_count: number | null;
3695
+ whale_trade_count: number | null;
3696
+ category_volume: number | null;
2860
3697
  })[] | null;
2861
- categories: Record<string, unknown>[] | null;
2862
3698
  /** Counts of current grades for distinct Polymarket traders with at least one whale alert in the report's source date range. The grade is the current projection at snapshot materialization time, not a historical grade at trade time. Traders without a current ranking projection are omitted; a null grade entry means the active trader's current grade is unavailable. */
2863
- grade_distribution: Record<string, unknown>[] | null;
3699
+ grade_distribution: ({
3700
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
3701
+ count: number | null;
3702
+ })[] | null;
2864
3703
  /** Which markets the report counts. sports_and_esports for a period that ends on or after 2026-10-21: totals, categories, top trades and the grade cohort cover sports and esports markets only. all_markets for an earlier period, whose stored report keeps every Polymarket market it published. */
2865
3704
  market_scope: "all_markets" | "sports_and_esports";
2866
3705
  };
@@ -2884,6 +3723,60 @@ export type ReportSourceRange = {
2884
3723
  end_date: string;
2885
3724
  timezone: "UTC";
2886
3725
  };
3726
+ export type ResolutionReport = {
3727
+ accuracy: number | null;
3728
+ all_wallets_accuracy: number | null;
3729
+ all_wallets_right: number | null;
3730
+ all_wallets_wrong: number | null;
3731
+ date: string | null;
3732
+ generated_at: string | null;
3733
+ grade_basis: "at_resolution" | "current" | null;
3734
+ market_scope: "all_markets" | "sports_and_esports";
3735
+ markets?: ({
3736
+ all_wallets_right: boolean | null;
3737
+ category: string | null;
3738
+ condition_id: string | null;
3739
+ confidence: number | null;
3740
+ event_slug: string | null;
3741
+ out_of_product_scope: boolean;
3742
+ outcome_no: string | null;
3743
+ outcome_yes: string | null;
3744
+ report_at: string;
3745
+ smart_consensus: string | null;
3746
+ smart_right: boolean | null;
3747
+ smart_trader_count: number | null;
3748
+ time_basis: "polymarket_gamma_closed_time" | "observed_resolution";
3749
+ title: string | null;
3750
+ total_smart_pnl: number | null;
3751
+ traders: ({
3752
+ address: string | null;
3753
+ correct: boolean | null;
3754
+ cost: number | null;
3755
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
3756
+ last_traded_at: string | null;
3757
+ pnl: number | null;
3758
+ side: string | null;
3759
+ username: string | null;
3760
+ })[];
3761
+ weighted_no: number | null;
3762
+ weighted_yes: number | null;
3763
+ winning_outcome: number | null;
3764
+ })[];
3765
+ markets_without_smart_positions: number | null;
3766
+ no_consensus: number | null;
3767
+ positions_grade_unknown: number | null;
3768
+ positions_without_side: number | null;
3769
+ smart_money_right: number | null;
3770
+ smart_money_wrong: number | null;
3771
+ source_updates_pending: boolean;
3772
+ time_basis_counts: {
3773
+ observed_resolution: number;
3774
+ polymarket_gamma_closed_time: number;
3775
+ } | null;
3776
+ total_resolved: number | null;
3777
+ total_smart_pnl: number | null;
3778
+ with_smart_positions: number | null;
3779
+ };
2887
3780
  export type ResponseMeta = {
2888
3781
  /** Unique request ID (req_ prefix). The same value as the X-Request-Id response header, the request's usage accounting row and its log lines. */
2889
3782
  request_id: string;
@@ -2954,7 +3847,7 @@ export type ScoreCell = {
2954
3847
  };
2955
3848
  /** Shape the provider score string was parsed into. `two_side` is one aggregate per side (basketball `105-98`), `multi_set` is per-set columns (tennis `6-7(5-7), 6-0, 1-0`), `esports_series` is a maps/sets/format triplet (`000-000|2-0|Bo3`). Omitted when the score could not be parsed. */
2956
3849
  export type ScoreFormat = "two_side" | "multi_set" | "esports_series";
2957
- /** `sharp_money_flow_detected` data (Pro and Max): ranked-trader net flow on a market crossed the threshold. The deprecated spelling `smart_money_flow_detected` delivers the same object. */
3850
+ /** `sharp_money_flow_detected` data (Pro and Max): ranked-trader net flow on a market crossed the threshold. The deprecated spelling `smart_money_flow_detected` delivers the same object until its sunset on 2027-02-01 (#29352). */
2958
3851
  export type SharpMoneyFlowDetectedData = {
2959
3852
  /** Polymarket condition id of the market. */
2960
3853
  condition_id: string;
@@ -2987,14 +3880,18 @@ export type SmartMoneyFlowMarket = {
2987
3880
  direction: "YES" | "NO";
2988
3881
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
2989
3882
  token_id: string | null;
2990
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
3883
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
2991
3884
  large_trade_count: number;
3885
+ /**
3886
+ * Deprecated spelling of large_trade_count, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_count.
3887
+ * @deprecated
3888
+ */
2992
3889
  whale_trade_count: number;
2993
3890
  buy_volume_usd: number;
2994
3891
  sell_volume_usd: number;
2995
3892
  };
2996
3893
  /**
2997
- * Deprecated alias of sharp_money; byte-identical and retained for backward compatibility.
3894
+ * Deprecated alias of sharp_money; byte-identical. Sunset 2027-02-01 (#29352): removed from V1 on that date; read sharp_money.
2998
3895
  * @deprecated
2999
3896
  */
3000
3897
  smart_money: {
@@ -3002,8 +3899,12 @@ export type SmartMoneyFlowMarket = {
3002
3899
  direction: "YES" | "NO";
3003
3900
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
3004
3901
  token_id: string | null;
3005
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
3902
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
3006
3903
  large_trade_count: number;
3904
+ /**
3905
+ * Deprecated spelling of large_trade_count, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trade_count.
3906
+ * @deprecated
3907
+ */
3007
3908
  whale_trade_count: number;
3008
3909
  buy_volume_usd: number;
3009
3910
  sell_volume_usd: number;
@@ -3015,8 +3916,12 @@ export type SnapshotCompleteness = {
3015
3916
  status: "complete" | "partial" | "empty";
3016
3917
  reason: string;
3017
3918
  expected_days: number;
3018
- /** Canonical key since #16304; covered_days_with_whale_activity is its deprecated spelling, emitted beside it with the same value. */
3919
+ /** Canonical key since #16304; covered_days_with_whale_activity is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
3019
3920
  covered_days_with_large_trade_activity: number;
3921
+ /**
3922
+ * Deprecated spelling of covered_days_with_large_trade_activity, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read covered_days_with_large_trade_activity.
3923
+ * @deprecated
3924
+ */
3020
3925
  covered_days_with_whale_activity: number;
3021
3926
  };
3022
3927
  export type SnapshotState = {
@@ -3036,6 +3941,50 @@ export type SnapshotState = {
3036
3941
  /** When this body's source read started, the clock finality is judged on. null for a body stored before that clock was recorded. */
3037
3942
  source_read_started_at: string | null;
3038
3943
  };
3944
+ export type SportLeaderboard = {
3945
+ as_of: string | null;
3946
+ category: string | null;
3947
+ edge_average: number | null;
3948
+ league: {
3949
+ name: string;
3950
+ ranked_traders: number;
3951
+ slug: string;
3952
+ } | null;
3953
+ limit: number;
3954
+ min_resolved: number;
3955
+ rows: ({
3956
+ address: string;
3957
+ cost: number | null;
3958
+ edge_hold: "category_loss" | "record_incomplete" | null;
3959
+ edge_skill: number | null;
3960
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
3961
+ id: string;
3962
+ last_category_trade_at: string | null;
3963
+ losses: number;
3964
+ n_resolved: number;
3965
+ platform: "polymarket";
3966
+ pnl: number | null;
3967
+ price_edge: {
3968
+ avg_price: number;
3969
+ edge: number;
3970
+ edge_lower: number;
3971
+ hit_rate: number;
3972
+ markets: number;
3973
+ status: "ranked" | "too_few_markets" | "sample_mismatch";
3974
+ } | null;
3975
+ rank: number;
3976
+ roi: number | null;
3977
+ username: string | null;
3978
+ volume: number | null;
3979
+ win_rate: number | null;
3980
+ win_rate_wilson_lb: number | null;
3981
+ wins: number;
3982
+ })[];
3983
+ sort: "edge" | "pnl" | "win_rate";
3984
+ sport: string;
3985
+ total_traders: number;
3986
+ volume_scope: "sports_and_esports";
3987
+ };
3039
3988
  export type SuspiciousTrade = {
3040
3989
  /** Prefixed ID (rf_...). */
3041
3990
  id: string;
@@ -3069,7 +4018,7 @@ export type SuspiciousTrade = {
3069
4018
  /** Stored trade timestamp. */
3070
4019
  created_at: string;
3071
4020
  };
3072
- /** `suspicious_trade_flagged` data (Pro and Max): a trade's suspicion score crossed the flag threshold for the first time. The deprecated spelling `insider_radar_flag_raised` delivers the same object. */
4021
+ /** `suspicious_trade_flagged` data (Pro and Max): a trade's suspicion score crossed the flag threshold for the first time. The deprecated spelling `insider_radar_flag_raised` delivers the same object until its sunset on 2027-02-01 (#29352). */
3073
4022
  export type SuspiciousTradeFlaggedData = {
3074
4023
  /** Numeric id of the flagged trade, a JSON number. It is the `id` that `GET /api/v1/large-trades/{id}` accepts. */
3075
4024
  trade_id: number;
@@ -3090,7 +4039,7 @@ export type SuspiciousTradeFlaggedData = {
3090
4039
  /** Fill price of the flagged trade. */
3091
4040
  price: number;
3092
4041
  };
3093
- /** Optional current-game tennis facts from API-Tennis, aligned with live_score.scores display order. These facts have their own revision and expiry; Polymarket remains the source of sets, match status, period, and the outer live-score revision. New observations require corroborated identity, current set/games, and live state. Cached responses and replayed frames may still carry expired facts, so clients must enforce expires_at. */
4042
+ /** Optional current-game tennis facts from API-Tennis, aligned with live_score.scores display order. These facts have their own revision and expiry; Polymarket remains the source of sets, match status, period, and the outer live-score revision. New observations require corroborated identity, current set/games, and live state. Where Polymarket publishes no score (tennis doubles, whose live_score reads one 0-0 set throughout), the group binds on both pairs' names, the tour, the date and API-Tennis's live flag, and carries set_games, the provider's set score for the match. Cached responses and replayed frames may still carry expired facts, so clients must enforce expires_at. */
3094
4043
  export type TennisPoints = {
3095
4044
  source: "api_tennis";
3096
4045
  /** API-Tennis match ID. This is not a Polymarket market or event ID. */
@@ -3107,10 +4056,12 @@ export type TennisPoints = {
3107
4056
  observed_at: string;
3108
4057
  /** Stop displaying the point group at this instant, even if the enclosing score remains fresh. The group expires 30 seconds after observed_at. */
3109
4058
  expires_at: string;
3110
- /** Current set number. Display points only while this matches the enclosing scoreboard. */
4059
+ /** Current set number. Display points only while this matches the enclosing scoreboard, unless set_games is present. */
3111
4060
  set_number: number;
3112
- /** Current-set games in first/second order. Display points only while these match the enclosing scoreboard. */
4061
+ /** Current-set games in first/second order. Display points only while these match the enclosing scoreboard, unless set_games is present. */
3113
4062
  games: number[];
4063
+ /** API-Tennis games in every listed set, first set first, each in first/second order. Present only when Polymarket publishes no score for the match (tennis doubles): display these as the set score, and discard the group once live_score carries a nonzero game. A deciding match tie-break is listed as games, for example 9-5. Omitted for every other match. */
4064
+ set_games?: number[][];
3114
4065
  };
3115
4066
  /** A provider-reported ATP/WTA singles rank with independent retrieval and expiry clocks. API-Tennis provides no ranking publication date. Retrieval time does not establish when the tour published the ranking. */
3116
4067
  export type TennisRanking = {
@@ -3140,33 +4091,52 @@ export type Trader = {
3140
4091
  forecast_evidence?: number;
3141
4092
  rank?: number;
3142
4093
  pnl: {
3143
- /** Polymarket's all-time leaderboard P&L in USD, from Polymarket's latest observation of this wallet on its all-time leaderboard (dated by the leaderboard_pnl data_quality group). Omitted when that leaderboard has no current observation ranking the wallet; 0xinsider requests one, and never serves an older stored figure in its place. Kept for provider parity and back-compat. Not the profile's Total P&L and not realized plus unrealized: it can differ from net_total by a wide margin. Read net_total for the figure the 0xinsider profile shows. */
4094
+ /**
4095
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's all-time leaderboard P&L, which covered every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29830). Read pnl.in_scope.realized_pnl.
4096
+ * @deprecated
4097
+ */
3144
4098
  total?: number;
3145
- /** Polymarket's net total P&L in USD: native Polymarket position P&L, with fees already included, plus credited maker and taker rebates (trader_trading_pnl.net_total_pnl). Truncated toward zero to cents before conversion to a JSON number. Omitted when the wallet has no native accounting snapshot; pnl.total is never substituted. The 0xinsider profile's Total P&L is this figure unless pnl.correction is present, then pnl.correction.net_total. */
4099
+ /**
4100
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's net total P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29830). Read pnl.in_scope.realized_pnl.
4101
+ * @deprecated
4102
+ */
3146
4103
  net_total?: number;
3147
- /** The 0xinsider correction to Polymarket's P&L for neg-risk conversions. Present only when one is published; pnl.net_total and pnl.realized keep Polymarket's own figures, and correction.net_total and correction.realized add the amount to them. */
4104
+ /**
4105
+ * Deprecated since 2026-10-27 and never sent. It was the neg-risk conversion correction to the wallet-wide pnl.net_total and pnl.realized (#29830). Its sports and esports part is inside pnl.in_scope.realized_pnl.
4106
+ * @deprecated
4107
+ */
3148
4108
  correction?: PnlCorrection;
3149
- /** true while 0xinsider is still checking some of the wallet's converted neg-risk markets (not yet measured, measured and not yet checked for transfers, or its latest reads keep failing), so the correction may change, or arrive where none is published yet. Omitted otherwise. */
4109
+ /** true while 0xinsider is still checking some of the wallet's converted neg-risk markets with a sports or esports event (not yet measured, measured and not yet checked for transfers, or its latest reads keep failing), so the correction's part inside pnl.in_scope.realized_pnl may change, or arrive where none is published yet. Omitted otherwise. */
3150
4110
  correction_pending?: boolean;
3151
- /** For pnl.realized, expand=trust marks a matching native accounting snapshot as computed: native Polymarket realized P&L plus credited maker and taker rebates, with fees already included. The exact numeric value is truncated toward zero to cents before conversion to a JSON number. Without a matching native accounting snapshot, pnl.realized is omitted and its trust metadata is unavailable. Raw total P&L is never substituted for realized P&L. */
4111
+ /**
4112
+ * Deprecated since 2026-10-27 and never sent. It was native Polymarket realized P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29830). Read pnl.in_scope.realized_pnl.
4113
+ * @deprecated
4114
+ */
3152
4115
  realized?: number;
4116
+ /** Unrealized P&L in USD of the wallet's open positions on its synced sports and esports markets, from the open-position aggregate (dated by the positions data_quality group). Each open position's market is judged when the aggregate is read (#32119), so a stored position on a market of another category (one that moved out of sports and esports, or one stored before its category was known) is left out. Before 2026-10-27 (#29366) it covered every Polymarket market. */
3153
4117
  unrealized?: number;
3154
- /** DEPRECATED, never sent. The local pnl_7d rollup over-counted P&L (#5416 class) and is no longer emitted. Read the provider-native weekly window from GET /api/trader/{address}/profile-summary instead. */
3155
- last_7d?: number;
3156
- /** DEPRECATED, never sent. The local pnl_30d rollup over-counted P&L (#5416 class) and is no longer emitted. Read the provider-native monthly window from GET /api/trader/{address}/profile-summary instead. */
3157
- last_30d?: number;
3158
- /** Additive lossless counterpart. Omitted when the trusted native realized-P&L source is unavailable; existing numeric fields keep their display-safe v1 semantics. */
4118
+ /**
4119
+ * Deprecated since 2026-10-27 and never sent: its one member was the lossless counterpart of the retired pnl.realized (#29830).
4120
+ * @deprecated
4121
+ */
3159
4122
  exact?: TraderPnlExact;
3160
- /** Additive (#27311): the wallet's sports and esports record, the figure the 0xinsider profile headlines. Omitted until 0xinsider has computed the wallet's record; absent means not computed yet, never zero. The other pnl fields stay Polymarket's wallet-wide figures. */
4123
+ /** Additive (#27311): the wallet's sports and esports record, the figure the 0xinsider profile headlines, dated by the sports_record data_quality group. Omitted until 0xinsider has computed the wallet's record; absent means not computed yet, never zero. Also omitted for a wallet that traded no sports or esports market, which never gets a record: then stats.markets_traded is 0 and the sports_record group is partial with owner traders.last_synced (since 2026-10-29, #30589, #30657). Also omitted for a wallet that trades only combos and holds no single sports or esports market: the record counts single markets, so it has none, stats.markets_traded and stats.win_rate are omitted, and the sports_record group is partial with owner traders.last_synced (since 2026-10-29, #30637). Since 2026-10-27 it is the wallet's only P&L figure besides pnl.unrealized (#29830). */
3161
4124
  in_scope?: TraderPnlInScope;
3162
4125
  };
4126
+ /** Sports and esports markets only since 2026-10-27 (#29830): markets_traded and win_rate come from the wallet's sports and esports record (pnl.in_scope), and total_volume from its stored trade days. A wallet that traded no sports or esports market never gets a record: markets_traded is 0 and win_rate is omitted (since 2026-10-29, #30589, #30657). A wallet that trades only combos has no record either: both are omitted (since 2026-10-29, #30637). */
3163
4127
  stats: {
4128
+ /** Sports and esports markets the wallet traded, any status: pnl.in_scope.markets, dated by the sports_record data_quality group. Omitted until the record is computed. 0 for a wallet that traded no sports or esports market, which never gets a record: at its last completed sync Polymarket counted no market for it, or the sync read its Polymarket positions and found no sports or esports market; none is stored, and no Polymarket sports or esports board lists it; the sports_record group then carries the sync clock (since 2026-10-29, #30589; the second case since #30657). Omitted for a wallet that trades only combos and holds no single sports or esports market, which has no record (since 2026-10-29, #30637). Counted every Polymarket market before 2026-10-27. */
3164
4129
  markets_traded?: number;
4130
+ /** Won over decided sports and esports markets, 0 to 1: pnl.in_scope.win_rate truncated to four places, dated by the sports_record data_quality group. Omitted until the record is computed, while the wallet has no decided sports or esports market, for a wallet that traded no sports or esports market (#30589, #30657), and for one that trades only combos (#30637). Counted every Polymarket market before 2026-10-27. */
3165
4131
  win_rate?: number;
4132
+ /**
4133
+ * Deprecated since 2026-10-27 and never sent. It counted mark-to-market days over every Polymarket market of the wallet (#29830). Read stats.all.win_days and stats.all.loss_days from GET /api/v1/trader/{address}/pnl, which count sports and esports days.
4134
+ * @deprecated
4135
+ */
3166
4136
  daily_win_rate?: number;
3167
- /** Full-history both-sides USD cash volume from Polymarket user-volume. Omitted without a verified observation; never leaderboard shares. Its observation time is published as the volume group in data_quality and as trust.total_volume.freshness.as_of, both trader_usd_volume.observed_at; synced_at is a different clock and is never a substitute for it. */
4137
+ /** Sports and esports USD volume, all time: the sum of every stored trade day's in-scope volume (trader_trade_daily_rollups.in_scope_volume_total), the profile's Volume traded. Dated by the volume data_quality group, which carries the trader sync clock. 0 for a synced wallet with no stored trade day. Omitted before the wallet's first completed sync and while any stored day's in-scope volume is not computed yet, so a partial sum is never served. Polymarket's full-history wallet-wide volume before 2026-10-27 (#29830). */
3168
4138
  total_volume?: number;
3169
- /** Additive lossless counterpart to `total_volume`. Omitted when the verified provider observation is unavailable. */
4139
+ /** Additive lossless counterpart to `total_volume`, present exactly when it is. */
3170
4140
  exact?: TraderStatsExact;
3171
4141
  };
3172
4142
  strategy?: {
@@ -3175,9 +4145,12 @@ export type Trader = {
3175
4145
  description?: string;
3176
4146
  confidence?: number;
3177
4147
  };
3178
- /** Per-category rank context when expand=categories is requested. Values include available rank, category totals, performance and record counts; scaled_total_pnl is a legacy alias of total_pnl. Its measurement basis and update timing differ from the plain record returned by GET /api/v1/trader/{address}/categories, so the two need not agree. Use this for rank context and that route for the plain record. The inner key-set is intentionally unconstrained and may contain additional compatibility fields. */
4148
+ /** Per-category rank context when expand=categories is requested. Values include available rank, category totals, performance and record counts; scaled_total_pnl is a legacy alias of total_pnl. Its measurement basis and update timing differ from the plain record returned by GET /api/v1/trader/{address}/categories, so the two need not agree. Use this for rank context and that route for the plain record. Sports and esports only (#28761): keys are sports and esports categories, and a category outside them is omitted, as on that route. The inner key-set is intentionally unconstrained and may contain additional compatibility fields. */
3179
4149
  category_strengths?: Record<string, unknown>;
3180
- /** Curated advanced risk/performance metrics (expand=quant_metrics or expand[]=quant_metrics). Omitted unless expanded and backed by a computed row strictly under six hours old; a missing row, NULL computed_at, or age of exactly six hours or more is stale and omitted. Provider-input changes may intentionally lag inside the bounded six-hour window. When present, all listed fields are present (each is a number or null); null means insufficient trade history and must not be treated as 0. The fixed field shape is unchanged. */
4150
+ /**
4151
+ * Deprecated since 2026-10-27 and never sent. These advanced risk and performance metrics covered every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29589). expand=quant_metrics is still accepted and adds nothing. For the sports and esports record read pnl.in_scope here, and GET /api/v1/trader/{address}/pnl for its daily series. The member shape below is what the object held before; it is kept so existing type declarations still compile.
4152
+ * @deprecated
4153
+ */
3181
4154
  quant_metrics?: {
3182
4155
  /** Trader smart score on a 0..100 display scale; higher is stronger. Null when unavailable. */
3183
4156
  smart_score: number | null;
@@ -3198,15 +4171,17 @@ export type Trader = {
3198
4171
  /** Cross-sectional percentile rank of edge consistency versus all traders, 0-100. null when insufficient history. */
3199
4172
  consistency_percentile: number | null;
3200
4173
  };
4174
+ /** When the wallet last traded: its most recent recorded trade, the same value the leaderboard entry's last_active carries (which re-reads it hourly). A cached body (meta.cached true) can lag a new trade by up to 60 seconds. No data_quality group dates it: the value is itself a trade time. Since 2026-11-02 (#32324); before, it carried the time 0xinsider last synced the wallet, the same value as synced_at. Omitted when the wallet has no recorded trade. */
3201
4175
  last_active?: string;
4176
+ /** When 0xinsider last completed a sync of the wallet (traders.last_synced), dated by the sync data_quality group. Not when the wallet traded: read last_active for that. */
3202
4177
  synced_at?: string;
3203
4178
  /** synced, unknown, or pending. */
3204
4179
  sync_status?: string;
3205
- /** Data age and coverage for this trader body. Always present. Its six groups are sync (traders.last_synced, covering pnl.net_total, pnl.realized, stats.markets_traded, stats.win_rate, stats.daily_win_rate, last_active, synced_at and sync_status), ranking (trader_rankings.computed_at, covering grade, score, streak_tier, forecast_score and forecast_evidence), leaderboard_rank (leaderboard_rank_refresh_state.completed_at, the completion time of the latest fully completed global rank refresh, covering rank), volume (trader_usd_volume.observed_at, covering stats.total_volume) and positions (trader_position_snapshots.last_refreshed_at with traders.last_synced as fallback, covering pnl.unrealized, the open-position aggregate) and leaderboard_pnl (trader_profile_provider_snapshots.observed_at, covering pnl.total: unavailable when Polymarket's all-time leaderboard has no current observation ranking the wallet). The positions clock is the latest successful /positions snapshot when one exists, otherwise the last completed trader sync; it does not date closed or native accounting values. A rank or position value remains unknown or unavailable when its clock or value is absent. For an unknown wallet every group is unavailable. If the open-position read itself fails, positions is unavailable with a reason that says so, pnl.unrealized is absent, and the body is answered fresh (meta.cached false) and is not kept for later callers. */
4180
+ /** Data age and coverage for this trader body. Always present. Its six groups are sync (traders.last_synced, covering synced_at and sync_status; it covered last_active until 2026-11-02, #32324, and no group covers last_active now, since the value is itself a trade time), sports_record (trader_product_scope_records.computed_at, covering pnl.in_scope, stats.markets_traded and stats.win_rate: unavailable until the wallet's sports and esports record is computed, partial while it has no decided sports or esports market; for a wallet that traded no sports or esports market, which never gets a record, partial with owner traders.last_synced, as of the completed sync that found none, stats.markets_traded 0 and pnl.in_scope and stats.win_rate omitted, since 2026-10-29, #30589, #30657; for a wallet that trades only combos and holds no single sports or esports market, partial with owner traders.last_synced and all three omitted, since 2026-10-29, #30637), ranking (trader_rankings.computed_at, covering grade, score, streak_tier, forecast_score and forecast_evidence), leaderboard_rank (leaderboard_rank_refresh_state.completed_at, the completion time of the latest fully completed global rank refresh, covering rank), volume (traders.last_synced, covering stats.total_volume, the sum of the trade days the sync stores: unavailable before the first completed sync and while a stored day's sports and esports volume is not computed) and positions (trader_position_snapshots.last_refreshed_at with traders.last_synced as fallback, covering pnl.unrealized, the open-position aggregate). Since 2026-10-27 (#29830) there is no leaderboard_pnl group, and volume is dated by the sync clock instead of trader_usd_volume.observed_at. The positions clock is the latest successful /positions snapshot when one exists, otherwise the last completed trader sync. A rank or position value remains unknown or unavailable when its clock or value is absent. For an unknown wallet every group is unavailable. If the open-position read itself fails, positions is unavailable with a reason that says so, pnl.unrealized is absent, and the body is answered fresh (meta.cached false) and is not kept for later callers. */
3206
4181
  data_quality: DataQuality;
3207
4182
  /** Field-level trust metadata. Present only when expand=trust or expand[]=trust is requested. */
3208
4183
  trust?: TraderTrust;
3209
- /** Current evidence for observed and known categories (expand=categories or expand[]=categories). Omitted unless expanded. Includes insufficient, stale, unknown and degraded rows; absence of a category is not proof of skill. The global grade is unchanged. */
4184
+ /** Current evidence for observed and known categories (expand=categories or expand[]=categories). Omitted unless expanded. Includes insufficient, stale, unknown and degraded rows; absence of a category is not proof of skill. The global grade is unchanged. Sports and esports only (#28827): a category outside them is omitted, as on GET /api/v1/trader/{address}/categories. */
3210
4185
  category_records?: CategorySkillV2[];
3211
4186
  category_skill_model?: CategorySkillModelReadiness;
3212
4187
  };
@@ -3240,31 +4215,37 @@ export type TraderCategoryRecords = {
3240
4215
  };
3241
4216
  export type TraderContext = {
3242
4217
  trader: Trader;
3243
- /** Aggregate position and P&L coverage for the trader. Counts all Polymarket markets, not only sports and esports. Omitted entirely (key absent, never null) when the trader is not in the local database or native net economics is unavailable. Realized fields remain numbers when present, including a genuine zero. */
4218
+ /** Aggregate position and P&L coverage for the trader, over its synced markets. markets_open, unrealized_mtm and cost_basis_locked cover the open positions on sports and esports markets, each market judged when the summary is read (#32119). markets_synced, markets_resolved and the resolved win figures count every stored market: since 2026-10-27 (#29366) those are mostly sports and esports markets, but a market that moved out of sports and esports, or one stored before its category was known, stays in them, and sync_coverage counts every category on both sides. markets_total, total_realized_pnl and synced_realized_pnl still cover every Polymarket market of the wallet. Omitted entirely (key absent, never null) when the trader is not in the local database or native net economics is unavailable. Realized fields remain numbers when present, including a genuine zero. */
3244
4219
  position_summary?: {
3245
- /** Provider markets_traded count when known; null when the provider total is unavailable. */
4220
+ /** Polymarket's count of the markets the wallet traded, every category, when known; null when the provider total is unavailable. */
3246
4221
  markets_total: number | null;
3247
4222
  /** Markets with locally synced position rows. */
3248
4223
  markets_synced: number;
3249
- /** Synced markets that have resolved. */
4224
+ /** Markets outside sports and esports that the wallet traded and whose synced rows 0xinsider deleted, counted when they were deleted (from 2026-10-27, #29366); 0 when none were. Not in markets_synced or any other count here; sync_coverage adds it to markets_synced so both sides of that ratio count every category. */
4225
+ markets_pruned: number;
4226
+ /** Markets outside sports and esports that the wallet first traded since 2026-10-26, which 0xinsider does not store, counted as the wallet syncs (#30165); 0 when none are. Not in markets_synced, markets_pruned or any other count here; sync_coverage adds it with markets_pruned to markets_synced. */
4227
+ markets_unstored: number;
4228
+ /** Combo markets the wallet traded, as maker or taker, counted from the combo fills 0xinsider indexes from the chain (#30218); 0 when it traded none. Polymarket counts each combo as one market in markets_total, and no position read lists one, so a combo is in no other count here; sync_coverage adds it with markets_pruned and markets_unstored to markets_synced. */
4229
+ markets_combo: number;
4230
+ /** Synced markets the wallet has settled: it closed its position by selling out, or the market resolved. Its P&L there is final. */
3250
4231
  markets_resolved: number;
3251
- /** Synced markets still open with residual value (open positions with current value > 0). */
4232
+ /** Synced sports and esports markets still open with residual value (open positions with current value > 0); a stored market of another category is left out (#32119). */
3252
4233
  markets_open: number;
3253
- /** markets_synced divided by markets_total when the provider total is known (capped at 1.0); 0.0-1.0. When markets_total is unknown or not positive (null, 0, or negative), this is 1.0 if any markets are synced (else 0.0), so cross-check markets_total before treating 1.0 as full coverage. */
4234
+ /** markets_synced plus markets_pruned plus markets_unstored plus markets_combo, divided by markets_total when the provider total is known (capped at 1.0); 0.0-1.0. Both sides count every category: no Polymarket count of a wallet's sports and esports markets exists, so the ratio does not estimate one. When markets_total is unknown or not positive (null, 0, or negative), this is 1.0 if that sum is positive (else 0.0), so cross-check markets_total before treating 1.0 as full coverage. */
3254
4235
  sync_coverage: number;
3255
- /** Native net realized P&L (USD) including credited rebates, minus the stored realized component of open positions with positive current value. Rebates are credited to the account, not to a position, so every credited rebate stays in this figure. NUMERIC arithmetic precedes conversion to a JSON number. */
4236
+ /** Native net realized P&L (USD) over every Polymarket market of the wallet, including credited rebates, minus the stored realized component of synced open positions with positive current value. Rebates are credited to the account, not to a position, so every credited rebate stays in this figure. NUMERIC arithmetic precedes conversion to a JSON number. */
3256
4237
  synced_realized_pnl: number;
3257
- /** Native net realized P&L (USD) including credited rebates, read directly from the accounting snapshot. Position sync_coverage is separate from this accounting basis. */
4238
+ /** Native net realized P&L (USD) over every Polymarket market of the wallet, including credited rebates, read directly from the accounting snapshot. For the sports and esports figure read trader.pnl.in_scope.realized_pnl. Position sync_coverage is separate from this accounting basis. */
3258
4239
  total_realized_pnl: number;
3259
- /** Mark-to-market unrealized P&L (USD) on open positions. */
4240
+ /** Mark-to-market unrealized P&L (USD) on open positions in synced sports and esports markets (#32119). */
3260
4241
  unrealized_mtm: number;
3261
- /** Cost basis (USD) currently tied up in open positions. */
4242
+ /** Cost basis (USD) currently tied up in open positions in synced sports and esports markets (#32119). */
3262
4243
  cost_basis_locked: number;
3263
- /** Win rate as a percentage (0-100): resolved_wins over resolved_decided. A resolved market that settled at exactly zero realized P&L (a void, a refund, a fully hedged position) is neither a win nor a loss and is not in the denominator, the same rule the leaderboard applies; null when no resolved market was decided. It is the rule of trader.stats.win_rate, read from the synced rows at request time; stats.win_rate is the stored figure the profile shows, refreshed by each sync and a few minutes after a closed-history write. context.md prints one Market win rate: this one when position_summary is present, else stats.win_rate. */
4244
+ /** Win rate as a percentage (0-100): resolved_wins over resolved_decided. A settled market that closed at exactly zero realized P&L (a void, a refund, a fully hedged position) is neither a win nor a loss and is not in the denominator, the same rule the leaderboard applies; null when no resolved market was decided. It is the rule of trader.stats.win_rate, read from the synced rows at request time; stats.win_rate is the stored figure the profile shows, refreshed by each sync and a few minutes after a closed-history write. context.md prints one Market win rate, stats.win_rate. */
3264
4245
  resolved_win_rate: number | null;
3265
- /** Resolved markets that settled at positive realized P&L: the win-rate numerator. Additive; null only on a summary cached before the field existed. */
4246
+ /** Settled markets that closed at positive realized P&L: the win-rate numerator. Additive; null only on a summary cached before the field existed. */
3266
4247
  resolved_wins: number | null;
3267
- /** Resolved markets that settled at a non-zero realized P&L: the win-rate denominator. At most markets_resolved; the difference is markets settled at exactly zero or with an unknown P&L. Additive; null only on a summary cached before the field existed. */
4248
+ /** Settled markets that closed at a non-zero realized P&L: the win-rate denominator. At most markets_resolved; the difference is markets settled at exactly zero or with an unknown P&L. Additive; null only on a summary cached before the field existed. */
3268
4249
  resolved_decided: number | null;
3269
4250
  /** RFC3339 freshness of the served OPEN-position data: the trader's latest /positions snapshot, else the last completed sync. The snapshot advances ONLY open positions, so read this as the open-position freshness clock -- the resolved/closed aggregates on this same summary (markets_resolved, resolved_win_rate) advance only on a full sync. The value is the /positions snapshot instant when one exists, so it is typically at or just before the trader-level last sync on a normal sync, and can be AFTER it while the active-view loop refreshes open positions between full syncs. This clock does not establish native accounting freshness. Always present on the wire (serialized as JSON null when the trader has neither a snapshot nor a sync); never omitted. */
3270
4251
  as_of: string | null;
@@ -3328,7 +4309,7 @@ export type TraderExportJob = {
3328
4309
  object: "trader_export_job";
3329
4310
  data: {
3330
4311
  job_id: number;
3331
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4312
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
3332
4313
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
3333
4314
  format: "json" | "ndjson" | "csv";
3334
4315
  /** Trade rows the file holds: trades in the wallet's sports and esports markets, counted in the file's own read snapshot. Null until the worker has read the snapshot (queued, and early in running); a job accepted before 2026-10-22 can carry the earlier all-markets estimate until its file is read. */
@@ -3359,7 +4340,7 @@ export type TraderExportJob = {
3359
4340
  cancel_requested_at: string | null;
3360
4341
  /** When the job reached cancelled; null until then. */
3361
4342
  cancelled_at: string | null;
3362
- /** Worker claims so far. */
4343
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
3363
4344
  attempt: number;
3364
4345
  /** The job fails when attempt reaches this. */
3365
4346
  max_attempts: number;
@@ -3393,7 +4374,7 @@ export type TraderExportPositionWatermark = {
3393
4374
  };
3394
4375
  export type TraderExportSnapshot = {
3395
4376
  address: string;
3396
- /** The markets the export file's trades and markets sections hold: sports and esports markets only. counts.exported_markets, counts.estimated_trade_rows, counts.estimated_size_mb, reconciliation.exported_market_cost_basis and source_range.latest_trade_at and latest_market_activity_at describe those markets. The pnl dates, pnl_days, exported_activity_volume and completeness cover every market of the wallet. */
4377
+ /** The markets the export file's trades and markets sections hold: sports and esports markets only. counts.exported_markets, counts.estimated_trade_rows, counts.estimated_size_mb, reconciliation.exported_market_cost_basis and source_range.latest_trade_at and latest_market_activity_at describe those markets, and reconciliation.exported_activity_volume is the cash the wallet traded in sports and esports markets. source_range.first_pnl_date, last_pnl_date and pnl_series_status and counts.pnl_days describe the file's pnl section, the wallet's sports and esports realized P&L by day. completeness.sync_coverage is the wallet's stored markets (its sports and esports markets since 2026-10-27, #29366) plus the markets of other categories whose rows were deleted and counted (position_summary.markets_pruned on the context) and those first traded since 2026-10-26, which are not stored and are counted as the wallet syncs (position_summary.markets_unstored, #30165) and its combo markets, which Polymarket counts and no position read lists (position_summary.markets_combo, #30218), over Polymarket's count of every market it traded: both sides count every category, so a fully synced wallet reads 1.0 and complete. A wallet with nothing stored and no pnl day is empty whatever its coverage. */
3397
4378
  product_scope: "sports_esports_v1";
3398
4379
  generated_at: string;
3399
4380
  source_range: ExportSourceRange;
@@ -3447,7 +4428,7 @@ export type TraderGradeAt = {
3447
4428
  source_observed_by: string | null;
3448
4429
  } | null;
3449
4430
  };
3450
- /** A trader's daily P&L object. `id` is always present. The five sections -- `entries`, `stats`, `monthly`, `year_totals`, `drawdown` -- are present unless the request's `sections` parameter excluded them, so a request that sends no `sections` always carries all five. An excluded section is absent from the object, never null and never an empty array. */
4431
+ /** A trader's sports and esports daily P&L object. `id`, `freshness_at`, `series_status` and `realized` are always present. The five sections -- `entries`, `stats`, `monthly`, `year_totals`, `drawdown` -- are present unless the request's `sections` parameter excluded them, so a request that sends no `sections` always carries all five. An excluded section is absent from the object, never null and never an empty array. While `series_status` is `pending` the sections are empty and never mean zero. */
3451
4432
  export type TraderPnl = {
3452
4433
  /** Prefixed trader ID (`trd_...`). */
3453
4434
  id: string;
@@ -3474,18 +4455,35 @@ export type TraderPnl = {
3474
4455
  drawdown: number | null;
3475
4456
  } | null;
3476
4457
  };
3477
- /** RFC3339 served-freshness clock for this trader's PnL history = traders.daily_pnl_recomputed_at, when the daily_pnl read model this response is served from was last rebuilt; null when it has never been recomputed for the trader. Always present, so read it as a value that can be null rather than a key that can be missing. */
4458
+ /** RFC3339 served-freshness clock: when the wallet's sports and esports record, which this series is read from, was last computed, or, for a wallet that traded no sports or esports market (#30589, #30657) or trades only combos (#30637) and so has no record, its last completed sync; null while series_status is pending. Always present, so read it as a value that can be null rather than a key that can be missing. */
3478
4459
  freshness_at: string | null;
3479
- /** Daily cumulative-P&L series (oldest-first). Present unless the request's `sections` excluded it, and clipped to `from`/`to` when either is set. cumulative_profit and total_pnl stay cumulative from the start of the stored history, so a clipped slice keeps the same economic meaning; view.anchor carries the point before the window. */
3480
- entries?: {
4460
+ /** `ready` when the series is served; an empty one is a wallet with no sports or esports day, or one that traded no sports or esports market (#30589, #30657) or trades only combos (#30637). `pending` when the wallet's sports and esports record does not carry the daily series yet: every section is empty, realized is null, and the empty sections never mean zero. Retry later. */
4461
+ series_status: "ready" | "pending";
4462
+ /** How the daily series adds up to the wallet's Sports P&L, full precision: dated_pnl + undated_pnl = realized_pnl. null while series_status is pending, and for a wallet that traded no sports or esports market or trades only combos, which has no record (#30589, #30657, #30637). */
4463
+ realized: {
4464
+ /** The rule behind realized_pnl, the same basis as pnl.in_scope.basis on GET /api/v1/trader/{address}. */
4465
+ basis: "polymarket_sports_esports_v1" | "sports_esports_split_v1";
4466
+ /** The wallet's Sports P&L: pnl.in_scope.realized_pnl on GET /api/v1/trader/{address}. null when the wallet has no published realized figure. */
4467
+ realized_pnl: number | null;
4468
+ /** The sum of every day's daily_change over the full history, whatever from/to say. */
4469
+ dated_pnl: number;
4470
+ /** realized_pnl less dated_pnl. realized_pnl starts from Polymarket's figures under either basis (its sports and esports figures, or its published figure for the whole wallet split by cost) and the days from the per-market record, so undated_pnl holds the wallet's share of Polymarket rebates, the in-scope part of the neg-risk conversion correction, any market with no trade date, and the difference between Polymarket's figure and the per-market record, which on some wallets is most of it. null exactly when realized_pnl is. */
4471
+ undated_pnl: number | null;
4472
+ } | null;
4473
+ /** Sports and esports daily P&L series (oldest-first): one point for each UTC day with realized P&L or sports and esports volume. Present unless the request's `sections` excluded it, and clipped to `from`/`to` when either is set. cumulative_profit and total_pnl are the running sum of daily_change from the start of the history, so a clipped slice keeps the same economic meaning; view.anchor carries the point before the window. */
4474
+ entries?: ({
3481
4475
  date: string;
4476
+ /** Sports and esports markets this wallet traded on this UTC day, counted from the fills 0xinsider stores for it. Omitted on a day whose stored fills include a market outside sports and esports (stored before October 2026), where the count would include it, and on a day above 20 times the wallet's median day. */
3482
4477
  markets_traded?: number;
3483
- /** Cash in USD this wallet traded on this UTC day, buys and sells, summed from the fills 0xinsider has stored for it. Not Polymarket's share count, and not the full-history stats.total_volume on GET /api/v1/trader/{address}. Omitted, with markets_traded, on a day above 20 times the wallet's median day. */
4478
+ /** Volume in USD this wallet traded on this UTC day in sports and esports markets, buys and sells: each fill's size times its price, fees excluded, the measure of Polymarket user-volume `volume_usdc`, summed from the fills 0xinsider stores for it. A day stored before 2026-10-27 counts the cash each fill moved, fee included, until it is recomputed. Not Polymarket's share count, and not the full-history stats.total_volume on GET /api/v1/trader/{address}, which covers every market. Omitted on a day with realized P&L and no stored sports or esports fill, and, with markets_traded, on a day above 20 times the wallet's median day. */
3484
4479
  total_volume?: number;
4480
+ /** Running sum of daily_change through this day. */
3485
4481
  cumulative_profit?: number;
4482
+ /** The same running sum as cumulative_profit. */
3486
4483
  total_pnl?: number;
4484
+ /** Realized P&L of the wallet's sports and esports markets dated to this UTC day: a settled market on its resolution day, else its last trade day; an open market's realized part on its last trade day. 0 on a day with volume and nothing realized. */
3487
4485
  daily_change: number;
3488
- }[];
4486
+ })[];
3489
4487
  /** Pre-derived period stats. Present unless the request's `sections` excluded it. Always the published all/90d/30d/7d windows over the full stored history; `from`/`to` never recompute them over the request's range. */
3490
4488
  stats?: {
3491
4489
  all: {
@@ -3542,12 +4540,13 @@ export type TraderPnl = {
3542
4540
  };
3543
4541
  };
3544
4542
  /** Per-month P&L aggregation. Present unless the request's `sections` excluded it. Whole months over the full stored history, never clipped to `from`/`to`, so a month is never a partial month. */
3545
- monthly?: {
4543
+ monthly?: ({
3546
4544
  year: number;
3547
4545
  month: number;
3548
4546
  pnl: number;
3549
- markets_traded: number;
3550
- }[];
4547
+ /** The month's entries[].markets_traded summed: a market traded on several days counts once a day. null when a day of the month has total_volume and no markets_traded, a day whose stored fills include a market outside sports and esports, where a sum would undercount. A day with no stored fill, or above 20 times the wallet's median day, adds 0. */
4548
+ markets_traded: number | null;
4549
+ })[];
3551
4550
  /** Per-year P&L totals (ascending by year). Present unless the request's `sections` excluded it. Whole years over the full stored history, never clipped to `from`/`to`. */
3552
4551
  year_totals?: {
3553
4552
  year: number;
@@ -3560,34 +4559,34 @@ export type TraderPnl = {
3560
4559
  drawdown: number;
3561
4560
  }[];
3562
4561
  };
3563
- /** Lossless counterparts for trader P&L values. The object is omitted when no trusted native realized-P&L snapshot is available. */
4562
+ /** Deprecated since 2026-10-27 and never sent: pnl.exact held the lossless counterpart of the retired wallet-wide pnl.realized (#29830). The member shape below is what the object held before; it is kept so existing type declarations still compile. */
3564
4563
  export type TraderPnlExact = {
3565
4564
  /** Native Polymarket realized P&L plus credited maker and taker rebates, with fees included, from the trusted matching `trader_trading_pnl.net_realized_pnl` snapshot. */
3566
4565
  realized: ExactDecimal;
3567
4566
  };
3568
- /** A wallet's sports and esports record (#27311): Polymarket's published realized P&L (pnl.realized plus any published pnl.correction) split into the part earned on sports and esports markets. Fees, refunds and rebates stay in, apportioned by cost. A wallet wholly in sports keeps the published figure exactly; one with no sports market gets 0. Refreshed after each wallet sync; as_of dates it. */
4567
+ /** A wallet's sports and esports record (#27311). basis names the rule behind realized_pnl (#29370): polymarket_sports_esports_v1 is Polymarket's own realized P&L for the wallet in its sports and esports categories, plus the wallet's maker and taker rebates apportioned by its sports and esports share of its Polymarket volume (by cost while Polymarket reports no overall volume) and the in-scope part of any published neg-risk conversion correction; sports_esports_split_v1, used until both of the wallet's category figures are confirmed, is Polymarket's published wallet-wide realized P&L (with any published correction) split into the part earned on sports and esports markets, with fees, refunds and rebates apportioned by cost. Refreshed after each wallet sync and each read of Polymarket's category leaderboards; as_of dates the market counts. */
3569
4568
  export type TraderPnlInScope = {
3570
- /** Names the split rule, currently sports_esports_split_v1. A new value means the rule changed; compare figures only within one basis. */
4569
+ /** The rule behind realized_pnl: polymarket_sports_esports_v1 (Polymarket's sports and esports category figures plus apportioned rebates) or sports_esports_split_v1 (the published realized figure split by cost). A new value means the rule changed; compare figures only within one basis. */
3571
4570
  basis: string;
3572
- /** Sports and esports realized P&L in USD, display-safe. null when the wallet has no published realized figure to split. */
4571
+ /** Sports and esports realized P&L in USD, display-safe. null when the split basis has no published realized figure to split. */
3573
4572
  realized_pnl: number | null;
3574
4573
  /** Sports and esports markets the wallet has traded, any status. */
3575
4574
  markets: number;
3576
- /** Of those, the markets that have resolved. */
4575
+ /** Of those, the settled markets: the wallet closed its position by selling out, or the market resolved. Its P&L there is final. */
3577
4576
  markets_resolved: number;
3578
4577
  /** Share of decided sports and esports markets the wallet won, 0 to 1. null with no decided market. */
3579
4578
  win_rate: number | null;
3580
- /** The wallet's markets outside sports and esports, which 0xinsider no longer lists. */
4579
+ /** The wallet's markets outside sports and esports, which 0xinsider no longer lists: those it still stores, those whose rows it deleted and counted, and those of other categories first traded since 2026-10-26, which it does not store and counts as the wallet syncs (#30165). */
3581
4580
  markets_out_of_scope: number;
3582
4581
  /** When the record behind these figures was computed. */
3583
4582
  as_of: string;
3584
4583
  };
3585
- /** Lossless counterparts for trader statistics. The object is omitted when the verified provider observation is unavailable. */
4584
+ /** Lossless counterparts for trader statistics. The object is present exactly when stats.total_volume is. */
3586
4585
  export type TraderStatsExact = {
3587
- /** stats.total_volume as an exact decimal: full-history both-sides cash volume in USD, Polymarket user-volume `volume_usdc`, from the verified `trader_usd_volume` observation. Never Polymarket's share count. */
4586
+ /** stats.total_volume as an exact decimal: the sports and esports USD volume, the sum of every stored trade day's `trader_trade_daily_rollups.in_scope_volume_total` (#29830). Polymarket's full-history wallet-wide user volume before 2026-10-27. */
3588
4587
  total_volume: ExactDecimal;
3589
4588
  };
3590
- /** `trader_synced` data: a tracked wallet finished a sync pass and has a fresh grade. The deprecated spelling `whale_trader_synced` delivers the same object. */
4589
+ /** `trader_synced` data: a tracked wallet finished a sync pass and has a fresh grade. The deprecated spelling `whale_trader_synced` delivers the same object until its sunset on 2027-02-01 (#29352). */
3591
4590
  export type TraderSyncedData = {
3592
4591
  /** 0xinsider's numeric id for the wallet. */
3593
4592
  trader_id: number;
@@ -3596,15 +4595,25 @@ export type TraderSyncedData = {
3596
4595
  };
3597
4596
  /** Field-level trust metadata returned only when GET /api/v1/trader/{address} includes expand=trust. */
3598
4597
  export type TraderTrust = {
4598
+ /** Since 2026-10-27 always not_computed: pnl.total is retired and never sent (#29830). The key stays so the object keeps its shape. */
3599
4599
  total_pnl: TrustMetadata;
4600
+ /** Since 2026-10-27 always not_computed: pnl.realized and pnl.exact are retired and never sent (#29830). The key stays so the object keeps its shape. */
3600
4601
  realized_pnl: TrustMetadata;
4602
+ /** Since 2026-10-27 always not_computed: pnl.net_total is retired and never sent (#29830). The key stays so the object keeps its shape. */
3601
4603
  net_total_pnl: TrustMetadata;
3602
- /** Present only with pnl.correction: a computed value owned by trader_pnl_corrections, dated by the newest measurement behind it. */
4604
+ /**
4605
+ * Deprecated since 2026-10-27 and never sent: it was present only with pnl.correction, which is retired (#29830).
4606
+ * @deprecated
4607
+ */
3603
4608
  pnl_correction?: TrustMetadata;
3604
4609
  unrealized_pnl: TrustMetadata;
4610
+ /** Computed, owned by trader_product_scope_records (markets) and dated by the record's computed_at, since 2026-10-27 (#29830). For a wallet that traded no sports or esports market, which never gets a record, owned by traders (last_synced), the completed sync that found none, and dated by it, since 2026-10-29 (#30589, #30657; owned by traders (markets_traded) until #30657). */
3605
4611
  markets_traded: TrustMetadata;
4612
+ /** Computed, owned by trader_product_scope_records (win_rate) and dated by the record's computed_at, since 2026-10-27 (#29830). */
3606
4613
  win_rate: TrustMetadata;
4614
+ /** Since 2026-10-27 always not_computed: stats.daily_win_rate is retired and never sent (#29830). The key stays so the object keeps its shape. */
3607
4615
  daily_win_rate: TrustMetadata;
4616
+ /** Computed, owned by trader_trade_daily_rollups (in_scope_volume_total) and dated by traders.last_synced, since 2026-10-27 (#29830). */
3608
4617
  total_volume: TrustMetadata;
3609
4618
  grade: TrustMetadata;
3610
4619
  score: TrustMetadata;
@@ -3641,21 +4650,31 @@ export type TrendingWallet = {
3641
4650
  window_markets_traded: number;
3642
4651
  /** Distinct in-window UTC trade days from our trades (0 if the winner is not in our DB). */
3643
4652
  window_trade_days: number;
3644
- /** All-time trader grade; a separate axis from streak_tier. Led by realized profit (the money actually banked, about 95 percent of the grade), with forecasting calibration, risk-adjusted returns, and consistency as the tie-breaker and proven-trader guardrails: any grade above C requires verified net-positive realized profit, and the top grades also require a real resolved-market track record plus a survivable drawdown. Relative, so it drifts as the cohort moves. Omitted when the trader is Unranked (fewer than 5 markets, or too little verified record to cohort-rank). */
4653
+ /** All-time trader grade; a separate axis from streak_tier. Led by realized profit on sports and esports markets (the money actually banked, about 95 percent of the grade; since 2026-10-22, the sports and esports share of the wallet's realized P&L), with forecasting calibration, risk-adjusted returns, and consistency as the tie-breaker and proven-trader guardrails: any grade above C requires verified net-positive realized profit on those markets, and the top grades also require a real track record of resolved sports and esports markets plus a survivable drawdown. Relative, so it drifts as the cohort moves. Omitted when the trader is Unranked (fewer than 5 markets, or too little verified record to cohort-rank). */
3645
4654
  grade?: "S" | "A" | "B" | "C" | "D" | "F";
3646
4655
  /** Hot-streak tier (trailing-7d cross-sectional percentile). Omitted when there is no recent activity. */
3647
4656
  streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
3648
- /** Polymarket's net total P&L for the wallet in USD: native Polymarket position P&L across all markets, fees included, plus credited maker and taker rebates (trader_trading_pnl.net_total_pnl). The 0xinsider profile's Total P&L is this figure unless pnl_correction is present, then pnl_correction.net_total. Context only: it does not affect the ranking, which follows trending_pnl_usd. Omitted when the wallet is not in the 0xinsider database or has no native accounting snapshot; the Polymarket leaderboard all-time figure is never substituted. */
4657
+ /** Additive (#29971): the wallet's sports and esports realized P&L in USD, the same figure as pnl.in_scope.realized_pnl on GET /api/v1/trader/{address} and the 0xinsider profile's Sports P&L, as of the board's last rebuild. Context only: it does not affect the ranking, which follows trending_pnl_usd. Omitted when the wallet is not in the 0xinsider database or has no sports and esports record yet: absent means not computed, never zero. */
4658
+ in_scope_realized_pnl?: number;
4659
+ /**
4660
+ * Deprecated since 2026-10-27 and never sent. It was Polymarket's net total P&L over every Polymarket market of the wallet, and wallet figures cover sports and esports markets only (#29971). Read in_scope_realized_pnl.
4661
+ * @deprecated
4662
+ */
3649
4663
  all_time_pnl_usd?: number;
3650
- /** The 0xinsider correction to Polymarket's P&L for neg-risk conversions. Present only when one is published; all_time_pnl_usd keeps Polymarket's own figure and pnl_correction.net_total is the profile's Total P&L. */
4664
+ /**
4665
+ * Deprecated since 2026-10-27 and never sent. It was the neg-risk conversion correction to the wallet-wide all_time_pnl_usd (#29971). Its sports and esports part is inside in_scope_realized_pnl.
4666
+ * @deprecated
4667
+ */
3651
4668
  pnl_correction?: PnlCorrection;
3652
4669
  all_time_score?: number;
3653
4670
  last_synced?: string;
3654
- /** Shape-only daily P&L sparkline across the window, derived from Polymarket's documented user-pnl cumulative curve (GET /v2/user-pnl) converted to per-day deltas. It conveys the trend of the curve only and is NOT guaranteed to sum to trending_pnl_usd, which is the canonical leaderboard total. */
4671
+ /** The wallet's sports and esports realized P&L on each UTC day of the window, ascending, one point a day, pnl_usd 0 on a day with none: the same in-scope realized day series the trader P&L endpoint serves. Empty while daily_pnl_series_status is pending, which never means zero. It leaves out non-sports markets, so it does not sum to trending_pnl_usd, which is Polymarket's leaderboard figure across all markets. */
3655
4672
  daily_pnl_series: {
3656
4673
  date: string;
3657
4674
  pnl_usd: number;
3658
4675
  }[];
4676
+ /** `ready` when daily_pnl_series is served; an all-zero one is a wallet with no sports or esports P&L in the window. `pending` when the wallet's sports and esports record does not carry its daily series yet, or the wallet is not in the 0xinsider database: daily_pnl_series is empty and never means zero. Retry later. */
4677
+ daily_pnl_series_status: "ready" | "pending";
3659
4678
  };
3660
4679
  /** Whether the described value or result set is complete for its stated contract. */
3661
4680
  export type TrustCompleteness = {
@@ -3802,7 +4821,7 @@ export type WebhookEndpoint = {
3802
4821
  signing_secret?: string;
3803
4822
  verification?: WebhookVerification;
3804
4823
  };
3805
- /** Self-describing entry in the webhook event catalog: the event type a subscriber lists in event_types, when it fires, the data payload shape, and whether it currently fires (active) or is reserved (dormant, subscribable but not yet delivered). Pro-only event types (large_trades_inserted, whale_trades_inserted, wallet_grade_changed, suspicious_trade_flagged, insider_radar_flag_raised, sharp_money_flow_detected, smart_money_flow_detected) only deliver to API keys on an active Pro subscription. Export lifecycle event types (export_job_ready, export_job_failed, export_job_expired, export_job_cancelled) are owner-scoped to the API-key account that created the export and contain no download URL; use the authorized export status/download routes. Some entries are two spellings of one event: large_trades_inserted and whale_trades_inserted, trader_synced and whale_trader_synced, suspicious_trade_flagged and insider_radar_flag_raised, sharp_money_flow_detected and smart_money_flow_detected. Either spelling subscribes, and an endpoint receives deliveries under the spelling it registered. */
4824
+ /** Self-describing entry in the webhook event catalog: the event type a subscriber lists in event_types, when it fires, the data payload shape, and whether it currently fires (active) or is reserved (dormant, subscribable but not yet delivered). Pro-only event types (large_trades_inserted, whale_trades_inserted, wallet_grade_changed, suspicious_trade_flagged, insider_radar_flag_raised, sharp_money_flow_detected, smart_money_flow_detected) only deliver to API keys on an active Pro subscription. Export lifecycle event types (export_job_ready, export_job_failed, export_job_expired, export_job_cancelled) are owner-scoped to the API-key account that created the export and contain no download URL; use the authorized export status/download routes. Some entries are two spellings of one event: large_trades_inserted and whale_trades_inserted, trader_synced and whale_trader_synced, suspicious_trade_flagged and insider_radar_flag_raised, sharp_money_flow_detected and smart_money_flow_detected. Either spelling subscribes, and an endpoint receives deliveries under the spelling it registered. The deprecated spellings (whale_trades_inserted, whale_trader_synced, insider_radar_flag_raised, smart_money_flow_detected) reach their sunset on 2027-02-01 (#29352); register the canonical spelling. */
3806
4825
  export type WebhookEventDescriptor = {
3807
4826
  id: WebhookEventType;
3808
4827
  /** One-line description of when the event fires. */
@@ -3913,7 +4932,7 @@ export type WhaleDatasetJob = {
3913
4932
  object: "whale_dataset_job";
3914
4933
  data: {
3915
4934
  job_id: number;
3916
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4935
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
3917
4936
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
3918
4937
  format: "ndjson";
3919
4938
  total_trades: number | null;
@@ -3942,7 +4961,7 @@ export type WhaleDatasetJob = {
3942
4961
  cancel_requested_at: string | null;
3943
4962
  /** When the job reached cancelled; null until then. */
3944
4963
  cancelled_at: string | null;
3945
- /** Worker claims so far. */
4964
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
3946
4965
  attempt: number;
3947
4966
  /** The job fails when attempt reaches this. */
3948
4967
  max_attempts: number;
@@ -4020,7 +5039,7 @@ export interface OperationData {
4020
5039
  batchGetTraders: BatchTraderItem[];
4021
5040
  cancelTraderExport: {
4022
5041
  job_id: number;
4023
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5042
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4024
5043
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4025
5044
  format: "json" | "ndjson" | "csv";
4026
5045
  /** Trade rows the file holds: trades in the wallet's sports and esports markets, counted in the file's own read snapshot. Null until the worker has read the snapshot (queued, and early in running); a job accepted before 2026-10-22 can carry the earlier all-markets estimate until its file is read. */
@@ -4051,7 +5070,7 @@ export interface OperationData {
4051
5070
  cancel_requested_at: string | null;
4052
5071
  /** When the job reached cancelled; null until then. */
4053
5072
  cancelled_at: string | null;
4054
- /** Worker claims so far. */
5073
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4055
5074
  attempt: number;
4056
5075
  /** The job fails when attempt reaches this. */
4057
5076
  max_attempts: number;
@@ -4071,7 +5090,7 @@ export interface OperationData {
4071
5090
  };
4072
5091
  cancelWhaleDataset: {
4073
5092
  job_id: number;
4074
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5093
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4075
5094
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4076
5095
  format: "ndjson";
4077
5096
  total_trades: number | null;
@@ -4100,7 +5119,7 @@ export interface OperationData {
4100
5119
  cancel_requested_at: string | null;
4101
5120
  /** When the job reached cancelled; null until then. */
4102
5121
  cancelled_at: string | null;
4103
- /** Worker claims so far. */
5122
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4104
5123
  attempt: number;
4105
5124
  /** The job fails when attempt reaches this. */
4106
5125
  max_attempts: number;
@@ -4137,7 +5156,8 @@ export interface OperationData {
4137
5156
  getAccountIdentity: {
4138
5157
  user_id: number;
4139
5158
  credential_id: number;
4140
- credential_kind: "api_key" | "oauth_grant";
5159
+ /** The kind of credential that made the request: api_key is a full-access developer key, oauth_grant an OAuth access token, integration_key a named integration key with fixed scopes created on https://0xinsider.com/developers. Before integration_key was added, these keys reported oauth_grant. */
5160
+ credential_kind: "api_key" | "oauth_grant" | "integration_key";
4141
5161
  /** The credential is currently valid; revoked, expired or unknown credentials are rejected. */
4142
5162
  credential_status: "active";
4143
5163
  entitlement: {
@@ -4145,10 +5165,11 @@ export interface OperationData {
4145
5165
  /** When paid data access is lapsed, the caller should renew the subscription; otherwise null. */
4146
5166
  recovery_action: "renew_subscription" | null;
4147
5167
  };
4148
- /** Approved OAuth scopes; null for full developer-key access. */
5168
+ /** The scopes an OAuth grant or integration key carries; null for full developer-key access. */
4149
5169
  scopes: string[] | null;
4150
5170
  };
4151
5171
  getApiDiscovery: ApiDiscovery;
5172
+ getCategoryLeaderboard: CategoryLeader[];
4152
5173
  getCombo: ComboDetail;
4153
5174
  getCombosSummary: CombosSummary;
4154
5175
  getCoverage: Platforms;
@@ -4156,6 +5177,8 @@ export interface OperationData {
4156
5177
  getEdgeHunter: EdgeHunterBoard | EdgeHunterRankedSignal[] | EdgeHunterObservation[];
4157
5178
  getEventReplaySince: EventReplayEvent[];
4158
5179
  getGame: Game;
5180
+ getGameHolders: BatchGameHoldersItem[];
5181
+ getGameSharpMoney: GameSharpMoney;
4159
5182
  getHealth: {
4160
5183
  status: "ok" | "degraded" | "down" | "maintenance";
4161
5184
  db: boolean;
@@ -4186,15 +5209,20 @@ export interface OperationData {
4186
5209
  getMarketHolders: MarketHolder[];
4187
5210
  getMarketIntel: MarketFlow;
4188
5211
  getMarketSnapshot: MarketSnapshot;
5212
+ getMarketTopHolders: MarketTopHolders;
5213
+ getMarketWalletsInOut: MarketWalletsInOut;
4189
5214
  getMonthlyReportSnapshot: ReportSnapshot;
4190
5215
  getPickOfTheDay: PickOfTheDay | PickOfTheDayNoEntitledPicks;
4191
5216
  getPickOfTheDayArchive: PickOfTheDayArchive;
4192
5217
  getPickOfTheDayLedger: PickOfTheDayLedger;
4193
5218
  getPickOfTheDayLedgerEntry: PickOfTheDayLedgerEntry;
5219
+ getPickOfTheDayStats: PickOfTheDayStats;
4194
5220
  getPlatforms: Platforms;
4195
5221
  getPositionTimeline: PositionTimelineEvent[];
4196
5222
  getPositionTimelineById: PositionTimelineEvent[];
4197
5223
  getReports: ReportSnapshot;
5224
+ getResolutionReport: ResolutionReport;
5225
+ getSportLeaderboard: SportLeaderboard;
4198
5226
  getStream: string;
4199
5227
  getSuspiciousTrade: SuspiciousTrade;
4200
5228
  getTrader: Trader;
@@ -4204,7 +5232,7 @@ export interface OperationData {
4204
5232
  getTraderExportSnapshot: TraderExportSnapshot;
4205
5233
  getTraderExportStatus: {
4206
5234
  job_id: number;
4207
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5235
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4208
5236
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4209
5237
  format: "json" | "ndjson" | "csv";
4210
5238
  /** Trade rows the file holds: trades in the wallet's sports and esports markets, counted in the file's own read snapshot. Null until the worker has read the snapshot (queued, and early in running); a job accepted before 2026-10-22 can carry the earlier all-markets estimate until its file is read. */
@@ -4235,7 +5263,7 @@ export interface OperationData {
4235
5263
  cancel_requested_at: string | null;
4236
5264
  /** When the job reached cancelled; null until then. */
4237
5265
  cancelled_at: string | null;
4238
- /** Worker claims so far. */
5266
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4239
5267
  attempt: number;
4240
5268
  /** The job fails when attempt reaches this. */
4241
5269
  max_attempts: number;
@@ -4298,7 +5326,7 @@ export interface OperationData {
4298
5326
  getWeeklyReportSnapshot: ReportSnapshot;
4299
5327
  getWhaleDatasetStatus: {
4300
5328
  job_id: number;
4301
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5329
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4302
5330
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4303
5331
  format: "ndjson";
4304
5332
  total_trades: number | null;
@@ -4327,7 +5355,7 @@ export interface OperationData {
4327
5355
  cancel_requested_at: string | null;
4328
5356
  /** When the job reached cancelled; null until then. */
4329
5357
  cancelled_at: string | null;
4330
- /** Worker claims so far. */
5358
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4331
5359
  attempt: number;
4332
5360
  /** The job fails when attempt reaches this. */
4333
5361
  max_attempts: number;
@@ -4347,8 +5375,43 @@ export interface OperationData {
4347
5375
  filters: WhaleDatasetFilters;
4348
5376
  };
4349
5377
  getWhaleTrade: LargeTradeDetail;
5378
+ listCategoryLeaders: CategoryLeader[];
4350
5379
  listComboFills: ComboFill[];
5380
+ listGameMarkets: ({
5381
+ condition_id: string;
5382
+ event_slug: string;
5383
+ group_item_title?: string;
5384
+ id: string;
5385
+ line?: number;
5386
+ line_outcome_index?: number;
5387
+ negative_risk?: boolean;
5388
+ outcomes: {
5389
+ index: number;
5390
+ label?: string;
5391
+ token_id?: string;
5392
+ }[];
5393
+ platform?: string;
5394
+ slug?: string;
5395
+ sports_market_type?: string;
5396
+ status: string;
5397
+ title?: string;
5398
+ sharp_money?: {
5399
+ money_as_of: string | null;
5400
+ outcomes: {
5401
+ index: number;
5402
+ usd: number;
5403
+ wallets: {
5404
+ a: number;
5405
+ b: number;
5406
+ s: number;
5407
+ };
5408
+ }[];
5409
+ status: "computed" | "not_computed" | "unavailable";
5410
+ trader_count: number | null;
5411
+ };
5412
+ })[];
4351
5413
  listGames: Game[];
5414
+ listGameTrades: GameTrade[];
4352
5415
  listInsiderRadar: SuspiciousTrade[];
4353
5416
  listLargePositions: LargePosition[];
4354
5417
  listLargeTradeCounterpartyExecutions: CounterpartyAnalysis;
@@ -4356,6 +5419,7 @@ export interface OperationData {
4356
5419
  listLargeTradeHistory: LargeTrade[];
4357
5420
  listLargeTrades: LargeTrade[];
4358
5421
  listLeaderboard: LeaderboardEntry[];
5422
+ listLeaderboardLeagues: LeaderboardLeagues;
4359
5423
  listPositions: Position[];
4360
5424
  listSharpMoneyFlows: SmartMoneyFlowMarket[];
4361
5425
  listSmartMoneyFlows: SmartMoneyFlowMarket[];
@@ -4377,7 +5441,7 @@ export interface OperationData {
4377
5441
  searchMarkets: MarketSearchResult[];
4378
5442
  submitTraderExport: {
4379
5443
  job_id: number;
4380
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5444
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4381
5445
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4382
5446
  format: "json" | "ndjson" | "csv";
4383
5447
  /** Trade rows the file holds: trades in the wallet's sports and esports markets, counted in the file's own read snapshot. Null until the worker has read the snapshot (queued, and early in running); a job accepted before 2026-10-22 can carry the earlier all-markets estimate until its file is read. */
@@ -4408,7 +5472,7 @@ export interface OperationData {
4408
5472
  cancel_requested_at: string | null;
4409
5473
  /** When the job reached cancelled; null until then. */
4410
5474
  cancelled_at: string | null;
4411
- /** Worker claims so far. */
5475
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4412
5476
  attempt: number;
4413
5477
  /** The job fails when attempt reaches this. */
4414
5478
  max_attempts: number;
@@ -4428,7 +5492,7 @@ export interface OperationData {
4428
5492
  };
4429
5493
  submitWhaleDataset: {
4430
5494
  job_id: number;
4431
- /** queued: accepted, not started. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the hourly reconciler reads the object back and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
5495
+ /** queued: waiting for a worker. A running job reads queued again, with error saying why, when its worker restarts for a deploy (the next worker claims it within seconds) or stops without handing it back (requeued within a minute of its 30-minute lease lapsing); it starts again from the beginning. running: the worker is streaming rows. reconcile_required: the upload finished but the storage completion answer was lost; the reconciler reads the object back within a minute, retries a failed readback an hour later, and moves the job to ready or failed, and expires_at bounds the wait. ready: downloadable until expires_at. failed: terminal; error says why; submit a new export. expired: the retention window passed; the file is retired, the download route answers 410, submit a new export. cancel_requested: the owner cancelled a running job (POST /api/v1/trader/{address}/export/cancel); the worker stops at its next safe point and the job reads cancelled. cancelled: terminal; the owner cancelled the job and no file was published; submit a new export. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed, cancelled and expired rows stay readable for 48 hours, then the job answers 404. */
4432
5496
  status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
4433
5497
  format: "ndjson";
4434
5498
  total_trades: number | null;
@@ -4457,7 +5521,7 @@ export interface OperationData {
4457
5521
  cancel_requested_at: string | null;
4458
5522
  /** When the job reached cancelled; null until then. */
4459
5523
  cancelled_at: string | null;
4460
- /** Worker claims so far. */
5524
+ /** Worker claims so far. A claim handed back when its worker restarts for a deploy is not counted, so attempt steps back by one when the job reads queued again for that reason. */
4461
5525
  attempt: number;
4462
5526
  /** The job fails when attempt reaches this. */
4463
5527
  max_attempts: number;
@@ -4501,7 +5565,7 @@ export interface OperationQuery {
4501
5565
  status?: "active" | "closed" | "all";
4502
5566
  /** Filter by source platform. Explore is Polymarket-only; polymarket is the only supported value and the parameter is accepted for backward-compatibility but does not change the result set. */
4503
5567
  platform?: "polymarket";
4504
- /** Sort order for the discovery feed. `large_trades` ranks by large-trade activity; `whales` is its deprecated spelling and selects the same order. */
5568
+ /** Sort order for the discovery feed. `large_trades` ranks by large-trade activity; `whales` is its deprecated spelling and selects the same order until its sunset on 2027-02-01 (#29352); from then it answers 400 bad_request. */
4505
5569
  sort?: "trending" | "hot" | "expiring" | "large_trades" | "whales" | "volume" | "newest";
4506
5570
  /** Opaque pagination cursor from the previous response. */
4507
5571
  cursor?: string;
@@ -4512,6 +5576,16 @@ export interface OperationQuery {
4512
5576
  };
4513
5577
  getAccountIdentity: Record<string, never>;
4514
5578
  getApiDiscovery: Record<string, never>;
5579
+ getCategoryLeaderboard: {
5580
+ /** Keep wallets that traded in the category within this window. all (the default) keeps every ranked wallet. */
5581
+ active_within?: "all" | "7d" | "30d" | "90d";
5582
+ /** Independent events a wallet needs in the category to be listed. The site offers 0, 50, 100 and 250. Clamped to 0..1000000. */
5583
+ min_events?: number;
5584
+ /** Maximum number of leaders to return. Out-of-range values are clamped to 1..100. */
5585
+ limit?: number;
5586
+ /** Opaque cel_ pagination cursor from a prior response. It binds the lower-bound/independent-event/wallet boundary to the committed category-skill ranking and to the slug, active_within and min_events of the request that issued it; a cursor from another filter is 400 on cursor, and one issued before the ranking refreshed is 400 with error.reason=cursor_expired. */
5587
+ cursor?: string;
5588
+ };
4515
5589
  getCombo: Record<string, never>;
4516
5590
  getCombosSummary: Record<string, never>;
4517
5591
  getCoverage: Record<string, never>;
@@ -4524,9 +5598,9 @@ export interface OperationQuery {
4524
5598
  view?: "board" | "signals" | "observations";
4525
5599
  /** Legacy canonical bucket alias, now accepted in every view. Provider aliases canonicalize: NFL reaches Football and EPL reaches Soccer. Use leagues for a league-specific selection. An unmappable non-sport category returns an empty result and echoes category non_sport. Combines with other selection axes using AND. */
4526
5600
  category?: string;
4527
- /** Required for view=observations; wider_holder, in_play or emerging_pile. Rejected for board and signals. wider_holder covers pregame markets outside the funded slate. A market that enters the slate leaves wider_holder; view=signals lists it only while its holder pile leans to one side, its backed side has a holder at or above min_grade and its kickoff is within horizon_hours, and otherwise neither view lists it. Each refresh evaluates at most 8 markets per sport and cohort, wider_holder by soonest kickoff (most graded holders first among equal kickoffs) and in_play by most graded holders, so a market among a sport's 8 soonest stays evaluated until its game starts. wider_holder also evaluates up to 8 more markets per sport that kick off within 24 hours, most graded holders first, so the most-held markets appear up to a day before kickoff. Each of these keeps its place in later refreshes until its game starts while its holder page still shows a card or could not be read, so a more-held market waits for a free place instead of displacing it. Each row's admitted_by names its place, most_held or soonest_kickoff. The rest count in coverage.capacity_limited_markets. Emerging pile is a wider-holder projection with sharp_pct in [0.75,0.85), complete holder scans and future kickoff, not an independent population or arrival history. */
5601
+ /** Required for view=observations; wider_holder, in_play or emerging_pile. Rejected for board and signals. wider_holder covers pregame markets that view=signals does not list at its widest selection (horizon_hours=48, min_grade=B, no selector), so until kickoff a market is read in one view or the other. A market view=signals lists leaves wider_holder as primary_slate_candidate, and is a wider_holder candidate again in the first refresh after view=signals stops listing it; signals_as_of names the view=signals snapshot each refresh read. Each refresh evaluates at most 8 markets per sport and cohort, wider_holder by soonest kickoff (most graded holders first among equal kickoffs) and in_play by most graded holders, so a market among a sport's 8 soonest stays evaluated until its game starts. wider_holder also evaluates up to 8 more markets per sport that kick off within 24 hours, most graded holders first, so the most-held markets appear up to a day before kickoff. Each of these keeps its place in later refreshes until its game starts while its holder page still shows a card or could not be read, so a more-held market waits for a free place instead of displacing it. Each row's admitted_by names its place, most_held or soonest_kickoff. The rest count in coverage.capacity_limited_markets. Emerging pile is a wider-holder projection with sharp_pct in [0.75,0.85), complete holder scans and future kickoff, not an independent population or arrival history. */
4528
5602
  cohort?: "wider_holder" | "in_play" | "emerging_pile";
4529
- /** Opt-in admission rule for view=observations with cohort=wider_holder; rejected for every other view and cohort. most_held_48h returns the most-held selection instead of the default one: per sport, up to 8 wider_holder markets kicking off within 48 hours, most graded holders first, then most volume, then soonest kickoff, at most 4 per event. It is recomputed every refresh and keeps no place, so a more-held market displaces a less-held one; funded-slate markets stay excluded. Every row carries admitted_by most_held_48h, including a market the default selection also evaluates, and the response echoes admission. funnel, coverage, degraded and degradation_reasons describe this selection: a wider_holder candidate it did not take counts as capacity_limited. Its markets that no default place covers are read after every default market, at most once per 10 minutes, so a row can rest on a holder page up to 15 minutes old (holder_snapshot_at). Omit for the default selection. Cursors and ETags bind it. */
5603
+ /** Opt-in admission rule for view=observations with cohort=wider_holder; rejected for every other view and cohort. most_held_48h returns the most-held selection instead of the default one: per sport, up to 8 wider_holder markets kicking off within 48 hours, most graded holders first, then most volume, then soonest kickoff, at most 4 per event. It is recomputed every refresh and keeps no place, so a more-held market displaces a less-held one; markets view=signals lists stay excluded. Every row carries admitted_by most_held_48h, including a market the default selection also evaluates, and the response echoes admission. funnel, coverage, degraded and degradation_reasons describe this selection: a wider_holder candidate it did not take counts as capacity_limited. Its markets that no default place covers are read after every default market, at most once per 10 minutes, so a row can rest on a holder page up to 15 minutes old (holder_snapshot_at). Omit for the default selection. Cursors and ETags bind it. */
4530
5604
  admission?: "most_held_48h";
4531
5605
  /** Board and signals: S, A or B, default B. Requires a piled-side holder at the selected grade floor or better, without removing other holders. Rejected for observations. */
4532
5606
  min_grade?: "S" | "A" | "B";
@@ -4570,6 +5644,13 @@ export interface OperationQuery {
4570
5644
  expand?: "trade"[];
4571
5645
  };
4572
5646
  getGame: Record<string, never>;
5647
+ getGameHolders: {
5648
+ /** 1 to 25 condition_id values of this game's markets, comma-separated. The key may also repeat (condition_ids=a&condition_ids=b). A raw provider condition_id or the mkt_-prefixed market id. */
5649
+ condition_ids: string[];
5650
+ /** Holders per market. Out-of-range values are clamped to 1..100. */
5651
+ limit?: number;
5652
+ };
5653
+ getGameSharpMoney: Record<string, never>;
4573
5654
  getHealth: Record<string, never>;
4574
5655
  getInsiderRadarFlag: Record<string, never>;
4575
5656
  getLargeTrade: Record<string, never>;
@@ -4593,7 +5674,7 @@ export interface OperationQuery {
4593
5674
  min_grade?: "S" | "A" | "B";
4594
5675
  /** Maximum holders per page. Out-of-range values are clamped to 1..100. */
4595
5676
  limit?: number;
4596
- /** 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. */
5677
+ /** 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. Page-only cursors from before 2026-10-02 are no longer accepted and return 400 bad_request with param=cursor; restart without a cursor. A cursor remains valid across roster refreshes, which can still repeat or skip holders as the live roster changes. */
4597
5678
  cursor?: string;
4598
5679
  };
4599
5680
  getMarketIntel: {
@@ -4606,14 +5687,26 @@ export interface OperationQuery {
4606
5687
  /** Include trust metadata for current_price and spread_bps. Repeatable: trust. */
4607
5688
  expand?: "trust"[];
4608
5689
  };
5690
+ getMarketTopHolders: {
5691
+ /** Maximum holders per outcome. Out-of-range values are clamped to 1..100. `totals` covers the whole sample whatever the limit. */
5692
+ limit?: number;
5693
+ };
5694
+ getMarketWalletsInOut: {
5695
+ /** The window the nets are summed over, ending at the read's clock: 24h (the default) or 7d. */
5696
+ window?: "24h" | "7d";
5697
+ };
4609
5698
  getMonthlyReportSnapshot: {
4610
5699
  /** UTC report month in YYYY-MM format. A month that ends before 2024-03-01, the first day report data covers, or starts after tomorrow UTC returns 400 bad_request with error.param=month. */
4611
5700
  month: string;
4612
5701
  };
4613
- getPickOfTheDay: Record<string, never>;
5702
+ getPickOfTheDay: {
5703
+ /** A product day (America/New_York) in YYYY-MM-DD format, on or before today. Omit it, or send today, for the current read. A past day with no published pick returns 404 not_found with error.param=date; a date after today, or a value that is not a date, returns 400 bad_request with error.param=date. */
5704
+ date?: string;
5705
+ };
4614
5706
  getPickOfTheDayArchive: Record<string, never>;
4615
5707
  getPickOfTheDayLedger: Record<string, never>;
4616
5708
  getPickOfTheDayLedgerEntry: Record<string, never>;
5709
+ getPickOfTheDayStats: Record<string, never>;
4617
5710
  getPlatforms: Record<string, never>;
4618
5711
  getPositionTimeline: {
4619
5712
  /** Market condition_id. One timeline per (trader, market). */
@@ -4637,6 +5730,20 @@ export interface OperationQuery {
4637
5730
  /** Period token for the granularity. daily: UTC date YYYY-MM-DD. weekly: ISO week YYYY-WW for a durable canonical snapshot, or a from,to YYYY-MM-DD pair for an exact ephemeral range limited to 31 inclusive UTC days. A wider explicit range returns 400 invalid_query. monthly: UTC month YYYY-MM. A period that ends before 2024-03-01, the first day report data covers, or starts after tomorrow UTC returns 400 bad_request with error.param=period. */
4638
5731
  period: string;
4639
5732
  };
5733
+ getResolutionReport: {
5734
+ /** UTC report date in YYYY-MM-DD format, no later than today UTC. Any other value returns 400 bad_request with error.param=date. */
5735
+ date: string;
5736
+ /** `totals` returns the counts without `markets`. Any other value than full or totals returns 400 bad_request with error.param=view. */
5737
+ view?: "full" | "totals";
5738
+ };
5739
+ getSportLeaderboard: {
5740
+ /** A league slug of the sport, for example premier-league or cs2, from GET /api/v1/leaderboard/leagues. Omit it for the sport board. */
5741
+ league?: string;
5742
+ /** Ranking axis. Any other value returns 400 bad_request with error.param=sort. */
5743
+ sort?: "edge" | "pnl" | "win_rate";
5744
+ /** Rows to return from the top of the board. Out-of-range values are clamped to 1..100. */
5745
+ limit?: number;
5746
+ };
4640
5747
  getStream: {
4641
5748
  /** Query-string fallback for the Last-Event-ID resume cursor when the client cannot set the request header. Numeric cluster-shared sequence id; non-numeric or absent attaches live with no replay. A future or expired id emits resync. */
4642
5749
  last_event_id?: string;
@@ -4655,9 +5762,9 @@ export interface OperationQuery {
4655
5762
  };
4656
5763
  getSuspiciousTrade: Record<string, never>;
4657
5764
  getTrader: {
4658
- /** Backward-compatible alias for expand. Repeatable: strategy, categories, quant_metrics, trust. */
5765
+ /** Backward-compatible alias for expand. Repeatable: strategy, categories, trust. quant_metrics is accepted and returns nothing since 2026-10-27. */
4659
5766
  "expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
4660
- /** Include heavy fields and trust metadata. Repeatable: strategy, categories, quant_metrics, trust. */
5767
+ /** Include heavy fields and trust metadata. Repeatable: strategy, categories, trust. quant_metrics is accepted and returns nothing since 2026-10-27. */
4661
5768
  expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
4662
5769
  /** Opt into a whole-response freshness ceiling in seconds. The server returns 200 only when data_quality.status is fresh and data_quality.as_of is no older than this value; otherwise it returns 409 with error.reason=freshness_ceiling_unsatisfied. No refresh or alternate read is attempted. */
4663
5770
  max_age_s?: number;
@@ -4700,6 +5807,7 @@ export interface OperationQuery {
4700
5807
  };
4701
5808
  getWhaleDatasetStatus: Record<string, never>;
4702
5809
  getWhaleTrade: Record<string, never>;
5810
+ listCategoryLeaders: Record<string, never>;
4703
5811
  listComboFills: {
4704
5812
  /** CSV of pending, won, or lost; all clears the filter. Unknown results appear only in unfiltered lists. */
4705
5813
  result?: string;
@@ -4724,21 +5832,45 @@ export interface OperationQuery {
4724
5832
  /** Offset for ranked largest or payout ordering; use returned next_offset. */
4725
5833
  offset?: number;
4726
5834
  };
5835
+ listGameMarkets: {
5836
+ /** Comma-separated provider market types to keep, case-insensitive: spreads, totals, points, first_half_totals. Omitted keeps every type. An unknown type returns an empty page, not a 400; families lists the event's types. */
5837
+ sports_market_type?: string;
5838
+ /** active, closed or all. closed means the provider closed the market or it resolved. */
5839
+ status?: "active" | "closed" | "all";
5840
+ /** Page size. Out-of-range values are clamped to 1..100. */
5841
+ limit?: number;
5842
+ /** Opaque gmk_v1_ cursor from next_cursor, sent with the same filters. It pins the page position (sports_market_type, line, condition_id), not a snapshot. A cursor this endpoint did not issue returns 400 with error.param=cursor. */
5843
+ cursor?: string;
5844
+ /** sharp_money adds each row's sharp_money: the game page's per-line split, side USD and S, A and B wallet counts per outcome. One read for the event whatever the page size; the request costs 5 instead of 2. Pro and Max. Repeatable: sharp_money. */
5845
+ expand?: "sharp_money"[];
5846
+ /** Backward-compatible alias for expand. Repeatable: sharp_money. */
5847
+ "expand[]"?: "sharp_money"[];
5848
+ };
4727
5849
  listGames: {
4728
5850
  /** Canonical sport bucket, case-insensitive, with - and _ read as a space: table-tennis and Table Tennis are the same bucket. Omit for every covered sport. A bucket this deployment does not serve returns an empty page. */
4729
5851
  sport?: string;
4730
- /** League tag, case-insensitive, as coverage.leagues spells it: nfl, epl, cs2, euroleague. EuroLeague games use sport=Basketball and league=euroleague. Omit for every league inside the selected sports. */
5852
+ /** League tag, case-insensitive, as coverage.leagues spells it: nfl, epl, cs2, euroleague, cbb, cwbb. EuroLeague games use sport=Basketball and league=euroleague; NCAA men's and women's college basketball games use sport=Basketball with league=cbb and league=cwbb. Omit for every league inside the selected sports. */
4731
5853
  league?: string;
4732
- /** Keep only games in this state. A value outside the enum returns an empty page. */
5854
+ /** Keep only games in this state. ended, cancelled and postponed also list finished games that have left the live board, read from their stored records, for kickoffs within starts_after..starts_before (default: the 7 days before now). Without status, or with any other state, the list is the live and upcoming board. A value outside the enum returns an empty page. */
4733
5855
  status?: "scheduled" | "live" | "paused" | "ended" | "postponed" | "cancelled" | "suspended" | "delayed" | "unknown";
4734
- /** RFC 3339 instant. Keep only games whose kickoff is at or after it. Games with no published kickoff are excluded whenever either bound is set. */
5856
+ /** RFC 3339 instant. Keep only games whose kickoff is at or after it. Games with no published kickoff are excluded whenever either bound is set. With a finished status, the stored games' look-back starts here; omitted, it starts 7 days before starts_before, and nothing caps an earlier value. */
4735
5857
  starts_after?: string;
4736
5858
  /** RFC 3339 instant. Keep only games whose kickoff is at or before it. Must be at or after starts_after. */
4737
5859
  starts_before?: string;
5860
+ /** Which games to read. all, the default, lists the whole covered catalog, which can start with games the provider still holds open weeks after kickoff. now lists what is on now: every game the provider reports in play (live or paused), plus any other game whose kickoff was at most 3 hours ago or is still to come; ended, postponed and cancelled games are left out, and a game with no published kickoff stays and sorts last. Combines with every other filter. A value other than all or now returns 400 invalid_query with error.param=window. */
5861
+ window?: "all" | "now";
4738
5862
  /** Page size. Out-of-range values are clamped to 1..100. */
4739
5863
  limit?: number;
4740
- /** Opaque gms_v1_ cursor from next_cursor. It pins the page position (kickoff and event_slug), not a snapshot: the catalog is live, so a game added or removed between pages moves with it. A cursor this endpoint did not issue returns 400 with error.param=cursor. */
5864
+ /** Opaque gms_v1_ cursor from next_cursor. It pins the page position (kickoff and event_slug), not a snapshot: the catalog is live, so a game added or removed between pages moves with it. With a finished status, a page that spent its read budget carries a cursor past everything it read, which may be past the last game it returned. A cursor this endpoint did not issue returns 400 with error.param=cursor. */
4741
5865
  cursor?: string;
5866
+ /** Backward-compatible alias for expand. Repeatable: sharp_money. */
5867
+ "expand[]"?: "sharp_money"[];
5868
+ /** sharp_money adds each game's sharp_money, the GameSharpMoney object GET /api/v1/games/{event_slug}/sharp-money returns, read from the sport board's cached aggregate: one board read per sport on the page, never a per-game compute. A game the board did not evaluate carries status not_computed (read the per-game route for it); a sport whose aggregate could not be read carries status unavailable while the rest of the page is served. Adds 3 to the request cost. Repeatable. */
5869
+ expand?: "sharp_money"[];
5870
+ };
5871
+ listGameTrades: {
5872
+ /** Newest fills to return. Out-of-range values are clamped to 1..200. */
5873
+ limit?: number;
4742
5874
  };
4743
5875
  listInsiderRadar: {
4744
5876
  /** Maximum number of radar flags to return. Out-of-range values are clamped to 1..100. */
@@ -4761,7 +5893,7 @@ export interface OperationQuery {
4761
5893
  min_size?: number;
4762
5894
  /** One RFC 4180 CSV record of exact current provider-backed market_canonical.category values. Legacy unquoted lists such as NBA,WNBA remain valid; values containing commas, quotes, or newlines are CSV-quoted. Matching is case-insensitive. Malformed quoted input fails closed as one unknown exact category. A value outside sports and esports returns 400 bad_request with param=category (#27305), as on GET /api/v1/markets/explore. */
4763
5895
  category?: string;
4764
- /** Minimum trader grade. */
5896
+ /** Minimum trader grade. Matched against the trader.grade each row returns, the wallet's current grade, so every row listed shows a grade at or above this floor. */
4765
5897
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
4766
5898
  /** Scope to one market. Accepts the raw provider condition_id or the mkt_-prefixed market id (round-trips a value from a list response). Must be 0x followed by 64 hexadecimal characters after any mkt_ prefix is stripped; any other value returns 400. Polymarket-only; an unknown but well-formed id returns []. A market outside sports and esports returns 404 not_found with error.reason=market_out_of_scope (#27305). */
4767
5899
  condition_id?: string;
@@ -4809,6 +5941,8 @@ export interface OperationQuery {
4809
5941
  min_market_volume_share?: number;
4810
5942
  /** Order of the returned page. recent is newest first and is the default. market_volume_share ranks by each trade's share of its market's traded volume, biggest first, with a trade whose share is unavailable last. That ranking reads from, or the last 30 days when from is omitted, for the same reason. A cursor is bound to the order it was minted in, so a continuation cannot cross from one order into the other. */
4811
5943
  sort?: "recent" | "market_volume_share";
5944
+ /** Only the large trades in one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them. Matched case-insensitively. Newest first only (sort=market_volume_share answers 400), and cannot be combined with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
5945
+ event_slug?: string;
4812
5946
  };
4813
5947
  listLargeTrades: {
4814
5948
  /** Maximum number of recent large trades to return. Out-of-range values are clamped to 1..100. */
@@ -4829,17 +5963,28 @@ export interface OperationQuery {
4829
5963
  sort?: "recent" | "market_volume_share";
4830
5964
  /** Return only the trades recorded after this one. Pass the id of a large trade this API returned (wt_<n>, or the bare integer). The answer keeps the list shape and newest-first order, and next_cursor pages within it. After means commit order: a trade recorded late with an earlier traded_at is still returned, and a trade whose write has not committed yet is returned on a later poll, never skipped. To poll, send the id of the first trade on the first page of your last answer that had trades, with If-None-Match set to the ETag you last received; when nothing new was recorded the answer is 304 with an empty body. A late trade can come back once, so deduplicate on id. Only with sort=recent. An id that names no trade, or one more than 10000 trades behind the newest, answers 400 with error.param since; request the list without since and continue from its first trade. */
4831
5965
  since?: string;
5966
+ /** Only this market's large trades: an exact raw provider condition_id. The page is read from the market's own index, newest first, and pages with cursor; it cannot be combined with since or with event_slug (400). An unknown market returns an empty list. */
5967
+ condition_id?: string;
5968
+ /** Only the large trades in one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them. Matched case-insensitively. Newest first only (sort=market_volume_share answers 400), pages with cursor, and cannot be combined with since or with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
5969
+ event_slug?: string;
4832
5970
  };
4833
5971
  listLeaderboard: {
4834
5972
  /** Maximum number of ranked traders to return. Out-of-range values are clamped to 1..100. */
4835
5973
  limit?: number;
4836
- /** Opaque lbv1_ pagination cursor from a prior response. It binds the finite score/address boundary to the committed leaderboard generation and the effective category/strategy filters; legacy, malformed, non-finite, and unsupported-version cursors are rejected. */
5974
+ /** Opaque lbv1_ pagination cursor from a prior response. It binds the finite score/address boundary to the committed leaderboard generation and the effective category/strategy filters, and on a sorted page to its sort, dir and activity. A cursor from another sort or dir is a 400 bad_request on cursor; one from another activity, category, strategy or generation is cursor_expired. Legacy, malformed, non-finite, and unsupported-version cursors are rejected. */
4837
5975
  cursor?: string;
4838
5976
  /** Filter by category: a sport or esports bucket. Values are matched to canonical category buckets: league values fold into their sport (NBA and NCAAB into Basketball, NFL into Football). Mapped buckets are case-insensitive; passthrough buckets (Cricket, Sports) match case-sensitively against the provider-native bucket key, so use exact casing. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
4839
5977
  category?: string;
4840
- /** Filter by observed trading style. Current styles: two_sided, category_focused, high_activity, diversified, mixed, unclassified. Current styles count the wallet's sports and esports markets only. The original ten archetype identifiers remain accepted for historical rows until normal reclassification. Style describes recorded behavior; grade measures performance. */
4841
- strategy?: "accumulator" | "algo_trader" | "arbitrageur" | "category_focused" | "directional" | "diversified" | "event_driven" | "high_activity" | "market_maker" | "mixed" | "momentum" | "scalper" | "speculator" | "swing_trader" | "two_sided" | "unclassified";
4842
- };
5978
+ /** Filter by observed trading style. Current styles: two_sided, category_focused, high_activity, diversified, mixed, unclassified. Current styles count the wallet's sports and esports markets only. The ten archetype keys retired on 2026-10-01 (accumulator, algo_trader, arbitrageur, directional, event_driven, market_maker, momentum, scalper, speculator, swing_trader) are still accepted and match no wallet. Style describes recorded behavior; grade measures performance. */
5979
+ strategy?: "category_focused" | "diversified" | "high_activity" | "mixed" | "two_sided" | "unclassified";
5980
+ /** Order of the list, the sort columns of the site's leaderboard (/skill-leaderboard). rank (default) is the board's own order, the rank the site and the trader profile show. grade orders by score. volume orders by sports and esports USD volume, the figure GET /api/v1/trader/{address} serves as stats.total_volume. predictions orders by markets_traded. pnl orders by in_scope.realized_pnl. win_rate orders by win_rate among wallets with at least 5 decided sports and esports markets; a wallet with fewer sorts as having none. edge orders by price_edge.edge among wallets whose price_edge.status is ranked and that carry no price_edge.hold; any other wallet sorts as having none. The site's Edge column ranks those same wallets by their edge pulled toward the sports and esports average, a figure the API does not send, so the two orders can differ. A wallet without the value sorts as the lowest, so last in the natural direction and first with the direction reversed. Ties fall to address ascending. With ?category= a sort still orders by these whole-record figures; the category only decides which wallets are listed. Since 2026-11-02 (#32237; edge, #32270). */
5981
+ sort?: "rank" | "grade" | "volume" | "predictions" | "pnl" | "win_rate" | "edge";
5982
+ /** Direction of sort. Omitted, each sort reads in its natural direction: rank 1 first for rank (asc), largest first for every other sort (desc). The opposite value reverses the list. Since 2026-11-02 (#32237). */
5983
+ dir?: "asc" | "desc";
5984
+ /** Limit the list to wallets by recent trading, the site leaderboard's split. active: the wallet's last trade, as its current grade recorded it and aged to today, is 30 days old or less. inactive: older than 30 days, or no trade on record. all (default): every ranked wallet. Since 2026-11-02 (#32237). */
5985
+ activity?: "all" | "active" | "inactive";
5986
+ };
5987
+ listLeaderboardLeagues: Record<string, never>;
4843
5988
  listPositions: {
4844
5989
  /** Maximum number of current positions to return. Out-of-range values are clamped to 1..100. */
4845
5990
  limit?: number;
@@ -4877,6 +6022,10 @@ export interface OperationQuery {
4877
6022
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
4878
6023
  /** Optional post-aggregate flow direction filter. */
4879
6024
  direction?: "YES" | "NO";
6025
+ /** Only this market's flow: an exact raw provider condition_id. Cannot be combined with event_slug (400). An unknown market returns an empty list. */
6026
+ condition_id?: string;
6027
+ /** Only the markets of one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them, ranked as the unfiltered list ranks. Matched case-insensitively; cannot be combined with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
6028
+ event_slug?: string;
4880
6029
  };
4881
6030
  listSmartMoneyFlows: {
4882
6031
  /** Lookback window for grade-filtered whale flow aggregation. */
@@ -4893,6 +6042,10 @@ export interface OperationQuery {
4893
6042
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
4894
6043
  /** Optional post-aggregate flow direction filter. */
4895
6044
  direction?: "YES" | "NO";
6045
+ /** Only this market's flow: an exact raw provider condition_id. Cannot be combined with event_slug (400). An unknown market returns an empty list. */
6046
+ condition_id?: string;
6047
+ /** Only the markets of one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them, ranked as the unfiltered list ranks. Matched case-insensitively; cannot be combined with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
6048
+ event_slug?: string;
4896
6049
  };
4897
6050
  listSuspiciousTrades: {
4898
6051
  /** Maximum number of suspicious trades to return. Out-of-range values are clamped to 1..100. */
@@ -4965,6 +6118,8 @@ export interface OperationQuery {
4965
6118
  min_market_volume_share?: number;
4966
6119
  /** Order of the returned page. recent is newest first and is the default. market_volume_share ranks by each trade's share of its market's traded volume, biggest first, with a trade whose share is unavailable last. That ranking reads from, or the last 30 days when from is omitted, for the same reason. A cursor is bound to the order it was minted in, so a continuation cannot cross from one order into the other. */
4967
6120
  sort?: "recent" | "market_volume_share";
6121
+ /** Only the large trades in one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them. Matched case-insensitively. Newest first only (sort=market_volume_share answers 400), and cannot be combined with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
6122
+ event_slug?: string;
4968
6123
  };
4969
6124
  listWhaleTrades: {
4970
6125
  /** Maximum number of recent large trades to return. Out-of-range values are clamped to 1..100. */
@@ -4985,6 +6140,10 @@ export interface OperationQuery {
4985
6140
  sort?: "recent" | "market_volume_share";
4986
6141
  /** Return only the trades recorded after this one. Pass the id of a large trade this API returned (wt_<n>, or the bare integer). The answer keeps the list shape and newest-first order, and next_cursor pages within it. After means commit order: a trade recorded late with an earlier traded_at is still returned, and a trade whose write has not committed yet is returned on a later poll, never skipped. To poll, send the id of the first trade on the first page of your last answer that had trades, with If-None-Match set to the ETag you last received; when nothing new was recorded the answer is 304 with an empty body. A late trade can come back once, so deduplicate on id. Only with sort=recent. An id that names no trade, or one more than 10000 trades behind the newest, answers 400 with error.param since; request the list without since and continue from its first trade. */
4987
6142
  since?: string;
6143
+ /** Only this market's large trades: an exact raw provider condition_id. The page is read from the market's own index, newest first, and pages with cursor; it cannot be combined with since or with event_slug (400). An unknown market returns an empty list. */
6144
+ condition_id?: string;
6145
+ /** Only the large trades in one game: every market of the game behind this event slug, the moneyline, spreads, totals and props, as GET /api/v1/games/{event_slug}/trades reads them. Matched case-insensitively. Newest first only (sort=market_volume_share answers 400), pages with cursor, and cannot be combined with since or with condition_id (400). An unknown slug answers 404 not_found with error.param event_slug. */
6146
+ event_slug?: string;
4988
6147
  };
4989
6148
  prepareWebhookSecret: Record<string, never>;
4990
6149
  redeliverWebhookDelivery: Record<string, never>;
@@ -4998,7 +6157,7 @@ export interface OperationQuery {
4998
6157
  limit?: number;
4999
6158
  };
5000
6159
  searchMarkets: {
5001
- /** Search query. Must be 1-512 characters before whitespace trimming and non-empty after trimming. */
6160
+ /** Search query. Must be 2-512 characters before whitespace trimming and hold at least 2 letters or digits after trimming; a query with fewer letters or digits (a, 7, ?) returns 400 bad_request with param q (#32309). */
5002
6161
  q: string;
5003
6162
  /** Maximum number of matching markets to return. Out-of-range values are clamped to 1..100. */
5004
6163
  limit?: number;
@@ -5049,6 +6208,10 @@ export interface OperationPath {
5049
6208
  exploreMarkets: Record<string, never>;
5050
6209
  getAccountIdentity: Record<string, never>;
5051
6210
  getApiDiscovery: Record<string, never>;
6211
+ getCategoryLeaderboard: {
6212
+ /** The category slug, for example soccer, basketball, tennis or esports, as GET /api/v1/leaderboard/categories lists it lowercased. Matched case-insensitively. */
6213
+ slug: string;
6214
+ };
5052
6215
  getCombo: {
5053
6216
  /** Combo identifier: 0x followed by 62 lowercase hex characters. This differs from a binary market condition ID. */
5054
6217
  condition_id: string;
@@ -5062,6 +6225,14 @@ export interface OperationPath {
5062
6225
  /** The game's event slug, for example nfl-buf-nyj-2026-09-22. Matched case-insensitively. */
5063
6226
  event_slug: string;
5064
6227
  };
6228
+ getGameHolders: {
6229
+ /** The game's event slug from GET /api/v1/games, for example nba-bos-orl-2026-11-01. Matched case-insensitively. */
6230
+ event_slug: string;
6231
+ };
6232
+ getGameSharpMoney: {
6233
+ /** The game's event slug, for example nba-bos-orl-2026-11-01. Matched case-insensitively; the response carries the canonical slug. */
6234
+ event_slug: string;
6235
+ };
5065
6236
  getHealth: Record<string, never>;
5066
6237
  getInsiderRadarFlag: {
5067
6238
  /** Raw whale_alerts.id or rf_-prefixed radar flag id. */
@@ -5095,6 +6266,14 @@ export interface OperationPath {
5095
6266
  /** Market condition ID. Accepts the raw provider-backed condition_id returned by /api/v1/markets/search or /api/v1/markets/explore, or the mkt_-prefixed market.id emitted by V1 responses. */
5096
6267
  condition_id: string;
5097
6268
  };
6269
+ getMarketTopHolders: {
6270
+ /** 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. */
6271
+ condition_id: string;
6272
+ };
6273
+ getMarketWalletsInOut: {
6274
+ /** Market condition ID. Accepts the raw provider-backed condition_id returned by /api/v1/markets/search or /api/v1/markets/explore, or the mkt_-prefixed market.id emitted by V1 responses. */
6275
+ condition_id: string;
6276
+ };
5098
6277
  getMonthlyReportSnapshot: Record<string, never>;
5099
6278
  getPickOfTheDay: Record<string, never>;
5100
6279
  getPickOfTheDayArchive: Record<string, never>;
@@ -5103,6 +6282,7 @@ export interface OperationPath {
5103
6282
  /** Stable positive pick row id as canonical decimal text. */
5104
6283
  pick_id: string;
5105
6284
  };
6285
+ getPickOfTheDayStats: Record<string, never>;
5106
6286
  getPlatforms: Record<string, never>;
5107
6287
  getPositionTimeline: {
5108
6288
  /** Trader identity: 0x... wallet address, username, trd_-prefixed trader id, bare integer traders.id, or @username. Resolved with precedence @username -> wallet -> trd_ -> integer -> username (a leading @ forces a username lookup, for all-digit usernames); wallet matching is case-insensitive. */
@@ -5113,6 +6293,11 @@ export interface OperationPath {
5113
6293
  trader: string;
5114
6294
  };
5115
6295
  getReports: Record<string, never>;
6296
+ getResolutionReport: Record<string, never>;
6297
+ getSportLeaderboard: {
6298
+ /** The sport slug, for example soccer, basketball, football or esports. Matched case-insensitively. A league or title alias such as nba, epl or cs2 reads its sport's board, and the body's sport is that board's slug; pass league for one league's board. */
6299
+ sport: string;
6300
+ };
5116
6301
  getStream: Record<string, never>;
5117
6302
  getSuspiciousTrade: {
5118
6303
  /** Raw whale_alerts.id or rf_-prefixed suspicious trade id. */
@@ -5170,8 +6355,17 @@ export interface OperationPath {
5170
6355
  /** Raw whale_alerts.id or wt_-prefixed whale trade id. */
5171
6356
  id: string;
5172
6357
  };
6358
+ listCategoryLeaders: Record<string, never>;
5173
6359
  listComboFills: Record<string, never>;
6360
+ listGameMarkets: {
6361
+ /** The event slug from GET /api/v1/games, GET /api/v1/games/{event_slug} or a markets/search result's event_slug, for example nba-bos-orl-2026-11-01. Matched case-insensitively. */
6362
+ event_slug: string;
6363
+ };
5174
6364
  listGames: Record<string, never>;
6365
+ listGameTrades: {
6366
+ /** The game's event slug, for example nfl-buf-nyj-2026-09-22. Matched case-insensitively. */
6367
+ event_slug: string;
6368
+ };
5175
6369
  listInsiderRadar: Record<string, never>;
5176
6370
  listLargePositions: Record<string, never>;
5177
6371
  listLargeTradeCounterpartyExecutions: {
@@ -5187,6 +6381,7 @@ export interface OperationPath {
5187
6381
  listLargeTradeHistory: Record<string, never>;
5188
6382
  listLargeTrades: Record<string, never>;
5189
6383
  listLeaderboard: Record<string, never>;
6384
+ listLeaderboardLeagues: Record<string, never>;
5190
6385
  listPositions: Record<string, never>;
5191
6386
  listSharpMoneyFlows: Record<string, never>;
5192
6387
  listSmartMoneyFlows: Record<string, never>;
@@ -5271,10 +6466,10 @@ export interface OperationBody {
5271
6466
  createMcpJsonRpcResponse: {
5272
6467
  /** JSON-RPC protocol version; this server accepts 2.0. */
5273
6468
  jsonrpc: "2.0";
5274
- /** Request identifier echoed exactly in one JSON-RPC response; supported notifications omit it and receive an empty HTTP 202. */
5275
- id?: string | number | null;
6469
+ /** Request identifier, a string or a number, echoed exactly in one JSON-RPC response; a notification omits it and receives an empty HTTP 202. A null id answers HTTP 400 with JSON-RPC error -32600. */
6470
+ id?: string | number;
5276
6471
  /** MCP method to invoke. */
5277
- method: "initialize" | "notifications/initialized" | "notifications/cancelled" | "ping" | "tools/list" | "tools/call";
6472
+ method: "initialize" | "notifications/initialized" | "notifications/cancelled" | "ping" | "tools/list" | "tools/call" | "server/discover";
5278
6473
  /** Method-specific MCP parameters. */
5279
6474
  params?: Record<string, unknown>;
5280
6475
  };
@@ -5284,6 +6479,7 @@ export interface OperationBody {
5284
6479
  exploreMarkets: never;
5285
6480
  getAccountIdentity: never;
5286
6481
  getApiDiscovery: never;
6482
+ getCategoryLeaderboard: never;
5287
6483
  getCombo: never;
5288
6484
  getCombosSummary: never;
5289
6485
  getCoverage: never;
@@ -5291,6 +6487,8 @@ export interface OperationBody {
5291
6487
  getEdgeHunter: never;
5292
6488
  getEventReplaySince: never;
5293
6489
  getGame: never;
6490
+ getGameHolders: never;
6491
+ getGameSharpMoney: never;
5294
6492
  getHealth: never;
5295
6493
  getInsiderRadarFlag: never;
5296
6494
  getLargeTrade: never;
@@ -5300,15 +6498,20 @@ export interface OperationBody {
5300
6498
  getMarketHolders: never;
5301
6499
  getMarketIntel: never;
5302
6500
  getMarketSnapshot: never;
6501
+ getMarketTopHolders: never;
6502
+ getMarketWalletsInOut: never;
5303
6503
  getMonthlyReportSnapshot: never;
5304
6504
  getPickOfTheDay: never;
5305
6505
  getPickOfTheDayArchive: never;
5306
6506
  getPickOfTheDayLedger: never;
5307
6507
  getPickOfTheDayLedgerEntry: never;
6508
+ getPickOfTheDayStats: never;
5308
6509
  getPlatforms: never;
5309
6510
  getPositionTimeline: never;
5310
6511
  getPositionTimelineById: never;
5311
6512
  getReports: never;
6513
+ getResolutionReport: never;
6514
+ getSportLeaderboard: never;
5312
6515
  getStream: never;
5313
6516
  getSuspiciousTrade: never;
5314
6517
  getTrader: never;
@@ -5325,8 +6528,11 @@ export interface OperationBody {
5325
6528
  getWeeklyReportSnapshot: never;
5326
6529
  getWhaleDatasetStatus: never;
5327
6530
  getWhaleTrade: never;
6531
+ listCategoryLeaders: never;
5328
6532
  listComboFills: never;
6533
+ listGameMarkets: never;
5329
6534
  listGames: never;
6535
+ listGameTrades: never;
5330
6536
  listInsiderRadar: never;
5331
6537
  listLargePositions: never;
5332
6538
  listLargeTradeCounterpartyExecutions: never;
@@ -5334,6 +6540,7 @@ export interface OperationBody {
5334
6540
  listLargeTradeHistory: never;
5335
6541
  listLargeTrades: never;
5336
6542
  listLeaderboard: never;
6543
+ listLeaderboardLeagues: never;
5337
6544
  listPositions: never;
5338
6545
  listSharpMoneyFlows: never;
5339
6546
  listSmartMoneyFlows: never;
@@ -5439,6 +6646,15 @@ export interface OperationResponse {
5439
6646
  data: OperationData["getApiDiscovery"];
5440
6647
  meta: ResponseMeta;
5441
6648
  };
6649
+ getCategoryLeaderboard: {
6650
+ object: "list";
6651
+ data: OperationData["getCategoryLeaderboard"];
6652
+ has_more: boolean;
6653
+ next_cursor?: string;
6654
+ /** Wallets in the category whose edge lower bound is above zero, Wallets in the full walk across every page: those in the category, under this request's active_within and min_events, whose edge lower bound is above zero. The same on every page. */
6655
+ total?: number;
6656
+ meta: ResponseMeta;
6657
+ };
5442
6658
  getCombo: ComboResponse;
5443
6659
  getCombosSummary: CombosSummaryResponse;
5444
6660
  getCoverage: {
@@ -5466,6 +6682,16 @@ export interface OperationResponse {
5466
6682
  as_of: string;
5467
6683
  meta: ResponseMeta;
5468
6684
  };
6685
+ getGameHolders: {
6686
+ object: "game_holders_batch";
6687
+ data: OperationData["getGameHolders"];
6688
+ meta: BatchResponseMeta;
6689
+ };
6690
+ getGameSharpMoney: {
6691
+ object: "game_sharp_money";
6692
+ data: OperationData["getGameSharpMoney"];
6693
+ meta: ResponseMeta;
6694
+ };
5469
6695
  getHealth: {
5470
6696
  object: "health";
5471
6697
  data: OperationData["getHealth"];
@@ -5515,6 +6741,16 @@ export interface OperationResponse {
5515
6741
  data: OperationData["getMarketSnapshot"];
5516
6742
  meta: ResponseMeta;
5517
6743
  };
6744
+ getMarketTopHolders: {
6745
+ object: "market_top_holders";
6746
+ data: OperationData["getMarketTopHolders"];
6747
+ meta: ResponseMeta;
6748
+ };
6749
+ getMarketWalletsInOut: {
6750
+ object: "market_wallets_in_out";
6751
+ data: OperationData["getMarketWalletsInOut"];
6752
+ meta: ResponseMeta;
6753
+ };
5518
6754
  getMonthlyReportSnapshot: {
5519
6755
  object: "report_snapshot";
5520
6756
  data: OperationData["getMonthlyReportSnapshot"];
@@ -5540,6 +6776,11 @@ export interface OperationResponse {
5540
6776
  data: OperationData["getPickOfTheDayLedgerEntry"];
5541
6777
  meta: ResponseMeta;
5542
6778
  };
6779
+ getPickOfTheDayStats: {
6780
+ object: "pick_of_the_day_stats";
6781
+ data: OperationData["getPickOfTheDayStats"];
6782
+ meta: ResponseMeta;
6783
+ };
5543
6784
  getPlatforms: {
5544
6785
  object: "platforms";
5545
6786
  data: OperationData["getPlatforms"];
@@ -5568,6 +6809,16 @@ export interface OperationResponse {
5568
6809
  data: OperationData["getReports"];
5569
6810
  meta: ResponseMeta;
5570
6811
  };
6812
+ getResolutionReport: {
6813
+ object: "resolution_report";
6814
+ data: OperationData["getResolutionReport"];
6815
+ meta: ResponseMeta;
6816
+ };
6817
+ getSportLeaderboard: {
6818
+ object: "sport_leaderboard";
6819
+ data: OperationData["getSportLeaderboard"];
6820
+ meta: ResponseMeta;
6821
+ };
5571
6822
  getStream: string;
5572
6823
  getSuspiciousTrade: {
5573
6824
  object: "suspicious_trade";
@@ -5628,18 +6879,52 @@ export interface OperationResponse {
5628
6879
  data: OperationData["getWhaleTrade"];
5629
6880
  meta: ResponseMeta;
5630
6881
  };
6882
+ listCategoryLeaders: {
6883
+ object: "list";
6884
+ data: OperationData["listCategoryLeaders"];
6885
+ has_more: boolean;
6886
+ next_cursor?: string;
6887
+ /** Number of rows returned: up to three per category. */
6888
+ total?: number;
6889
+ meta: ResponseMeta;
6890
+ };
5631
6891
  listComboFills: ComboFillsResponse;
6892
+ listGameMarkets: {
6893
+ data: OperationData["listGameMarkets"];
6894
+ event_slug: string;
6895
+ families: {
6896
+ active: number;
6897
+ markets: number;
6898
+ sports_market_type?: string;
6899
+ }[];
6900
+ has_more: boolean;
6901
+ meta: ResponseMeta;
6902
+ next_cursor?: string;
6903
+ object: string;
6904
+ };
5632
6905
  listGames: {
5633
6906
  object: "list";
5634
6907
  data: OperationData["listGames"];
5635
6908
  has_more: boolean;
5636
6909
  /** Pass as cursor for the next page. Present only when has_more is true. */
5637
6910
  next_cursor?: string;
5638
- /** When this read assembled the catalog. Per-source vintage is on each game's freshness. */
6911
+ /** When this read assembled the catalog; with status ended, cancelled or postponed, when it read the stored records. Per-source vintage is on each game's freshness. */
5639
6912
  as_of: string;
5640
6913
  coverage: GamesCoverage;
5641
6914
  meta: ResponseMeta;
5642
6915
  };
6916
+ listGameTrades: {
6917
+ object: "list";
6918
+ /** Newest first. */
6919
+ data: OperationData["listGameTrades"];
6920
+ /** Always false: the list is the game's newest limit fills, not a walk. Poll again for newer fills. */
6921
+ has_more: boolean;
6922
+ /** The game the rows were read for, lowercased. */
6923
+ event_slug: string;
6924
+ /** true when the rows are the game's last complete read, served while its refresh runs. Read again in a few seconds for the live rows. */
6925
+ source_stale: boolean;
6926
+ meta: ResponseMeta;
6927
+ };
5643
6928
  listInsiderRadar: {
5644
6929
  object: "list";
5645
6930
  data: OperationData["listInsiderRadar"];
@@ -5700,6 +6985,11 @@ export interface OperationResponse {
5700
6985
  total?: number;
5701
6986
  meta: ResponseMeta;
5702
6987
  };
6988
+ listLeaderboardLeagues: {
6989
+ object: "leaderboard_leagues";
6990
+ data: OperationData["listLeaderboardLeagues"];
6991
+ meta: ResponseMeta;
6992
+ };
5703
6993
  listPositions: {
5704
6994
  object: "list";
5705
6995
  data: OperationData["listPositions"];