@0xinsider/mcp 2.4.0 → 2.8.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.
Files changed (62) hide show
  1. package/README.md +23 -16
  2. package/dist/catalog.generated.d.ts +18 -6
  3. package/dist/catalog.generated.d.ts.map +1 -1
  4. package/dist/catalog.generated.js +21 -6
  5. package/dist/catalog.generated.js.map +1 -1
  6. package/dist/constants.d.ts +1 -1
  7. package/dist/constants.js +1 -1
  8. package/dist/product-cli/index.d.ts.map +1 -1
  9. package/dist/product-cli/index.js +5 -1
  10. package/dist/product-cli/index.js.map +1 -1
  11. package/dist/prompts/index.d.ts.map +1 -1
  12. package/dist/prompts/index.js +39 -25
  13. package/dist/prompts/index.js.map +1 -1
  14. package/dist/sdk/client.d.ts +106 -8
  15. package/dist/sdk/client.d.ts.map +1 -1
  16. package/dist/sdk/client.js +209 -12
  17. package/dist/sdk/client.js.map +1 -1
  18. package/dist/sdk/data-quality.d.ts +74 -0
  19. package/dist/sdk/data-quality.d.ts.map +1 -0
  20. package/dist/sdk/data-quality.js +68 -0
  21. package/dist/sdk/data-quality.js.map +1 -0
  22. package/dist/sdk/errors.d.ts +35 -1
  23. package/dist/sdk/errors.d.ts.map +1 -1
  24. package/dist/sdk/errors.js +51 -0
  25. package/dist/sdk/errors.js.map +1 -1
  26. package/dist/sdk/index.d.ts +14 -7
  27. package/dist/sdk/index.d.ts.map +1 -1
  28. package/dist/sdk/index.js +5 -3
  29. package/dist/sdk/index.js.map +1 -1
  30. package/dist/sdk/schema.d.ts +576 -105
  31. package/dist/sdk/schema.d.ts.map +1 -1
  32. package/dist/sdk/webhooks.d.ts +71 -12
  33. package/dist/sdk/webhooks.d.ts.map +1 -1
  34. package/dist/sdk/webhooks.js +22 -9
  35. package/dist/sdk/webhooks.js.map +1 -1
  36. package/dist/server.d.ts.map +1 -1
  37. package/dist/server.js +5 -2
  38. package/dist/server.js.map +1 -1
  39. package/dist/tools/{get-market-intel.d.ts → get-market-flow.d.ts} +3 -1
  40. package/dist/tools/get-market-flow.d.ts.map +1 -0
  41. package/dist/tools/get-market-flow.js +57 -0
  42. package/dist/tools/get-market-flow.js.map +1 -0
  43. package/dist/tools/get-positions.js +1 -1
  44. package/dist/tools/get-positions.js.map +1 -1
  45. package/dist/tools/get-trader.js +2 -2
  46. package/dist/tools/get-trader.js.map +1 -1
  47. package/dist/tools/get-whale-trades.js +2 -2
  48. package/dist/tools/get-whale-trades.js.map +1 -1
  49. package/dist/tools/pick-of-the-day.js +1 -1
  50. package/dist/tools/read-parity.d.ts +4 -1
  51. package/dist/tools/read-parity.d.ts.map +1 -1
  52. package/dist/tools/read-parity.js +67 -27
  53. package/dist/tools/read-parity.js.map +1 -1
  54. package/dist/tools/result.d.ts +2 -0
  55. package/dist/tools/result.d.ts.map +1 -1
  56. package/dist/tools/result.js +2 -0
  57. package/dist/tools/result.js.map +1 -1
  58. package/dist/tools/search-markets.js +1 -1
  59. package/package.json +1 -1
  60. package/dist/tools/get-market-intel.d.ts.map +0 -1
  61. package/dist/tools/get-market-intel.js +0 -39
  62. package/dist/tools/get-market-intel.js.map +0 -1
@@ -59,7 +59,7 @@ export type ApiDiscovery = {
59
59
  openapi_url: string;
60
60
  /** Unauthenticated API health endpoint. */
61
61
  health_url: string;
62
- authentication: "Bearer API key required for data endpoints; discovery (/api/v1), health, /api/v1/platforms, the Pick of the Day commitment ledger (/api/v1/pick-of-the-day/ledger), and the MCP handshake (initialize, ping, tools/list on /api/v1/mcp) are public. A 401 carries WWW-Authenticate with the resource_metadata URL.";
62
+ authentication: "Bearer API key required for data endpoints; discovery (/api/v1), health, coverage (/api/v1/coverage, and its deprecated alias /api/v1/platforms), the Pick of the Day commitment ledger (/api/v1/pick-of-the-day/ledger), and the MCP handshake (initialize, ping, tools/list on /api/v1/mcp) are public. A 401 carries WWW-Authenticate with the resource_metadata URL.";
63
63
  /** RFC 9728 protected-resource metadata for the API origin: the document every V1 401 names in its WWW-Authenticate challenge (resource, bearer_methods_supported, resource_documentation). The remote MCP server has its own document at /.well-known/oauth-protected-resource/api/v1/mcp. */
64
64
  protected_resource_metadata_url: string;
65
65
  /** The complete authenticated route index: one entry per authenticated route this spec documents, in "<METHOD> <path>" form, not a representative subset. GET /api/v1 is the unauthenticated entrypoint an agent hits first, so it hands back the whole authenticated surface rather than a sample the caller would have to guess around. The example on GET /api/v1 is abridged for readability -- the live response returns all of them. Kept in lockstep with this spec by review: it is a hand-maintained const in backend/src/api_v1/discovery.rs and no automated check compares the two, so treat this spec as authoritative if they ever disagree. */
@@ -75,8 +75,9 @@ export type ApiError = {
75
75
  param?: string;
76
76
  /** 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
77
  retry_at?: string;
78
+ freshness?: FreshnessFailure;
78
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 outside the HOT/WARM sync tiers -- stop asking for this wallet. 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 Pro 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. */
79
- reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "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";
80
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "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";
80
81
  };
81
82
  meta: ResponseMeta;
82
83
  };
@@ -88,15 +89,16 @@ export type ApiErrorBody = {
88
89
  param?: string;
89
90
  /** 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: before the 11:00 UTC operating-window start, before a selected pick's stored release, or after a skipped day, it names the automatic system's next boundary. While no candidate exists in the live window it normally names the persisted next automatic selector attempt. Every value is advisory under supported operator actions: manual publication, release-time override, or admin generation can make a pick available first. When the automatic schedule is absent/due or a pick is overdue it degrades to ~60s. Schedule one request and do not poll. Prefer Retry-After for the duration because it is immune to client clock skew. */
90
91
  retry_at?: string;
92
+ freshness?: FreshnessFailure;
91
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 outside the HOT/WARM sync tiers -- stop asking for this wallet. 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 Pro 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. */
92
- reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "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";
94
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "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";
93
95
  };
94
- export type BatchMarketIntelItem = {
96
+ export type BatchMarketFlowItem = {
95
97
  /** Zero-based request index. Duplicate inputs keep separate result rows. */
96
98
  index: number;
97
99
  input: string;
98
100
  status: "ok" | "error";
99
- data?: MarketIntel;
101
+ data?: MarketFlow;
100
102
  error?: ApiErrorBody;
101
103
  };
102
104
  export type BatchRateLimitMeta = {
@@ -250,6 +252,29 @@ export type CreateWebhookRequest = {
250
252
  /** Public HTTPS callback URL on the default port 443. Local, private, and internal targets are rejected, as is any explicit port other than 443 and any URL carrying credentials. Each user's URLs are unique after normalizing HTTPS scheme/host case, trailing DNS dots and port 443; path/query case is preserved. Pending verification and PATCH-disabled endpoints still reserve their stored URL. The destination must answer the signed webhook.verification challenge with a 2xx before POST /api/v1/webhooks/{id}/verify can activate the endpoint. */
251
253
  url: string;
252
254
  event_types: WebhookEventType[];
255
+ trade_filters?: LargeTradeSubscriptionFilters;
256
+ };
257
+ /** Compact data age and coverage for a response body, always present on the operations that publish it. Read status and as_of to decide whether to use the body at all, and field_groups to see which part is weak. Everything here comes from stored observation clocks, so a cached body reports the same ages a freshly computed one does: meta.cached and meta.cache_age_s stay the only transport-time facts and neither makes this block newer. The per-field audit object is still available through expand=trust; this is the default summary of the same question. */
258
+ export type DataQuality = {
259
+ /** fresh when every group is fresh, unavailable when every group is unavailable, and partial in every other case. */
260
+ status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
261
+ /** The oldest as_of among the groups that carry one: the age of the weakest clock this body rests on. Omitted when no group carries a clock. */
262
+ as_of?: string;
263
+ /** One entry per field group. Entries may be added in later releases, so match on group rather than on position or length. */
264
+ field_groups: DataQualityGroup[];
265
+ };
266
+ /** One group of response fields that share a writer and therefore share a clock. */
267
+ export type DataQualityGroup = {
268
+ /** Stable snake_case group name. Names are additive across releases, so match on the ones you know and ignore the rest. */
269
+ group: string;
270
+ /** The table and column that write this group, named so the verdict can be audited (for example trader_rankings.computed_at). */
271
+ owner: string;
272
+ /** fresh: served, and as_of carries this group's real observation or computation clock. partial: some of the group's fields are served and some are missing. unknown: served, and this read has no clock for it, so no age may be inferred. untracked: 0xinsider does not track this group for this subject, by design. unavailable: the group could not be served. New values may be added; treat one you do not recognize as unknown. fresh means the group is tracked and clocked, not that it is inside any particular tolerance: compare as_of against your own. */
273
+ status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
274
+ /** When this group's values were observed or computed. Omitted whenever the read cannot measure it, and never filled with the serialization time, the cache time, or another group's clock. */
275
+ as_of?: string;
276
+ /** Why the status is not fresh. Omitted when it is. */
277
+ reason?: string;
253
278
  };
254
279
  export type EventReplayEvent = {
255
280
  /** Opaque event identity: the ef_-encoded whale_alerts.id, stable across cursor formats. Deduplicate on this, never on cursor or sequence. */
@@ -331,6 +356,17 @@ export type EventReplaySource = {
331
356
  owner: "whale_alerts";
332
357
  provider_fetch_at_request_time: false;
333
358
  };
359
+ /** A lossless decimal atom rendered from the canonical NUMERIC or provider value. The value is a decimal string and must be parsed with a decimal library; it is never a display string and must not be converted through a binary float. `scale` is the source decimal scale. The field is omitted when its source is unavailable. */
360
+ export type ExactDecimal = {
361
+ /** Plain decimal text at full source precision, including a minus sign for negative values and trailing zeros when the source scale carries them. Parse as an arbitrary-precision decimal. */
362
+ value: string;
363
+ /** Unit of the value, such as `USD`, `USD/share`, or `shares`. */
364
+ unit: string;
365
+ /** Number of digits after the decimal point in `value`'s source atom. */
366
+ scale: number;
367
+ /** Backend-owned source or derivation basis. Treat it as provenance, not as a display label. */
368
+ basis: string;
369
+ };
334
370
  export type ExploreEntry = ExploreGroup | ExploreStandalone;
335
371
  export type ExploreFacets = {
336
372
  categories: ExploreFacetValue[];
@@ -420,6 +456,12 @@ export type ExploreMarket = {
420
456
  whale_signal: number | null;
421
457
  liquidity_signal: number | null;
422
458
  recency_signal: number | null;
459
+ /** Canonical key since #16308; smart_money_signal is its deprecated spelling, emitted beside it with the same value. */
460
+ sharp_money_signal: number | null;
461
+ /**
462
+ * Deprecated spelling of sharp_money_signal; emitted beside it with the same value and never removed.
463
+ * @deprecated
464
+ */
423
465
  smart_money_signal: number | null;
424
466
  price_move_signal: number | null;
425
467
  missing_price_penalty: number;
@@ -458,7 +500,17 @@ export type ExportVolumeReconciliation = {
458
500
  provider_activity_volume_gap: number | null;
459
501
  activity_volume_coverage: number | null;
460
502
  };
461
- /** One sports or esports game: both sides, its schedule, its provider status and the Polymarket markets linked to it. Assembled from the same provider-first live and upcoming projections the site's boards use, with no request-time provider fan-out. */
503
+ export type FreshnessFailure = {
504
+ /** The caller's requested whole-response freshness ceiling in seconds. */
505
+ max_age_s: number;
506
+ /** Age in seconds of the oldest stored data_quality.as_of clock, when one is available. */
507
+ actual_age_s?: number;
508
+ /** The oldest stored data-quality clock used to calculate actual_age_s, when one is available. */
509
+ as_of?: string;
510
+ /** The trader body's whole-response data-quality status. Only fresh can satisfy max_age_s. */
511
+ data_quality_status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
512
+ };
513
+ /** 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. */
462
514
  export type Game = {
463
515
  object: "game";
464
516
  /** 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. */
@@ -550,7 +602,64 @@ export type GameMarket = {
550
602
  outcome_no?: string;
551
603
  /** Polymarket CLOB token ids in the provider's own outcome-index order. Omitted when the provider has published none for this market. */
552
604
  outcome_token_ids?: string[];
605
+ /** Default provider moneyline state. Omitted when this market has no classified moneyline projection; incomplete and invalid projections remain explicit. */
606
+ prices?: GameMarketPrices;
607
+ };
608
+ /** How the existing sports-board writer bound prices to competitors. */
609
+ export type GameMarketPriceBindingProvenance = "provider_ids" | "exact_labels" | "containment_labels" | "elimination";
610
+ /** One competitor-bound provider moneyline price. No YES/NO inference is required. */
611
+ export type GameMarketPriceCompetitor = {
612
+ /** The provider competitor id when identity is available. */
613
+ provider_id?: number;
614
+ /** The provider competitor label. */
615
+ label: string;
616
+ /** Unrounded provider price in [0, 1]. */
617
+ price: number;
618
+ /** Which provider price observation supplies this leg. */
619
+ price_provenance: "gamma_outcome_prices" | "clob_display";
620
+ };
621
+ /** The provider moneyline pair is incomplete; no numeric pair is invented. */
622
+ export type GameMarketPriceIncomplete = {
623
+ state: "incomplete";
624
+ reason: "outcome_prices_missing" | "outcome_price_leg_missing" | "zero_price_sentinel" | "display_price_pair_unavailable" | "outcome_identity_unavailable" | "final_score_unavailable";
625
+ /** Whether competitor A is the provider YES leg. */
626
+ competitor_a_is_yes?: boolean;
627
+ /** The provider competitor id when identity is available. */
628
+ competitor_a_provider_id?: number;
629
+ /** The provider competitor id when identity is available. */
630
+ competitor_b_provider_id?: number;
631
+ binding_provenance?: GameMarketPriceBindingProvenance;
553
632
  };
633
+ /** The provider moneyline pair is invalid; no numeric pair is invented. */
634
+ export type GameMarketPriceInvalid = {
635
+ state: "invalid";
636
+ reason: "team_cardinality" | "outcome_cardinality" | "price_cardinality" | "non_finite_price" | "out_of_range_price" | "non_complementary_prices" | "ambiguous_identity" | "final_identity_mismatch";
637
+ /** Whether competitor A is the provider YES leg. */
638
+ competitor_a_is_yes?: boolean;
639
+ /** The provider competitor id when identity is available. */
640
+ competitor_a_provider_id?: number;
641
+ /** The provider competitor id when identity is available. */
642
+ competitor_b_provider_id?: number;
643
+ binding_provenance?: GameMarketPriceBindingProvenance;
644
+ };
645
+ /** A validated provider moneyline pair bound to the two competitors. */
646
+ export type GameMarketPricePaired = {
647
+ state: "paired";
648
+ competitor_a: GameMarketPriceCompetitor;
649
+ competitor_b: GameMarketPriceCompetitor;
650
+ /** Whether competitor A is the provider YES leg. */
651
+ competitor_a_is_yes: boolean;
652
+ binding_provenance: GameMarketPriceBindingProvenance;
653
+ };
654
+ /** Provider-owned moneyline state with the observation clock that can be compared with game freshness. */
655
+ export type GameMarketPrices = {
656
+ provider: GameMarketProviderPrices;
657
+ /** Board cache vintage for Gamma or the older CLOB leg clock. Null when no reliable clock is available; never a Gamma-authored timestamp. */
658
+ observed_at: string | null;
659
+ /** The clock used for observed_at. board_snapshot is this service’s cache observation, not a provider source timestamp. */
660
+ observation_source: "board_snapshot" | "clob_display";
661
+ };
662
+ export type GameMarketProviderPrices = GameMarketPricePaired | GameMarketPriceIncomplete | GameMarketPriceInvalid;
554
663
  /** What this deployment covers, published with every page so a client never has to guess whether an empty list means no games or no coverage. */
555
664
  export type GamesCoverage = {
556
665
  /** Canonical sport buckets served, sorted. */
@@ -586,7 +695,7 @@ export type HolderCategoryEvidence = {
586
695
  export type LargeExportPolicy = {
587
696
  mode: "v1_async_export";
588
697
  current_internal_route: string;
589
- /** Programmatic API-key-gated export routes (submit/status/download) and supported formats (json, ndjson, csv). */
698
+ /** Programmatic API-key-gated export routes (submit/status/download/cancel) and supported formats (json, ndjson, csv). */
590
699
  v1_async: {
591
700
  /** POST route template to submit an export job. fresh=true asks for a snapshot read after the submit instead of reusing a finished one. */
592
701
  submit_route?: string;
@@ -594,10 +703,12 @@ export type LargeExportPolicy = {
594
703
  status_route?: string;
595
704
  /** GET route template that 302-redirects to the file. */
596
705
  download_route?: string;
706
+ /** POST route template to cancel a queued or running job. */
707
+ cancel_route?: string;
597
708
  /** Supported ?format= values. */
598
709
  formats?: ("json" | "ndjson" | "csv")[];
599
710
  /** Possible job status values. */
600
- status_values?: ("queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired")[];
711
+ status_values?: ("queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled")[];
601
712
  /** How long a finished export is retained before expiry. */
602
713
  retention?: string;
603
714
  };
@@ -687,9 +798,19 @@ export type LargeTrade = {
687
798
  /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the traded outcome; null when unavailable (e.g. unsynced markets) and for a Polymarket trade recorded before 2026-04-02T00:00:00Z, where the traded side is unknown. */
688
799
  token_id: string | null;
689
800
  price: number;
690
- /** Current 0.0–1.0 normalized signal score, computed at request time from the trader's win rate today and the trade's age now. On a historical row it is today's view of the trade, not what a reader saw then; use recorded_signal_score for that. */
801
+ /** Current 0.0–1.0 review score, computed at request time from the trade's size, the trader's win rate today, a bonus when a trader with a win rate above 55% trades at a price below 30¢, and the trade's age now. A higher score means read this trade first; it does not measure edge or predict an outcome. On a historical row it is today's view of the trade, not what a reader saw then; use recorded_review_score for that. Canonical since #16311; signal_score carries the same value. */
802
+ review_score: number;
803
+ /**
804
+ * Current 0.0–1.0 review score, computed at request time from the trader's win rate today and the trade's age now. Deprecated (#16311): `review_score` is the canonical spelling and carries the same value; this key stays on the wire.
805
+ * @deprecated
806
+ */
691
807
  signal_score: number;
692
- /** 0.0–1.0 signal 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. */
808
+ /** 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. */
809
+ recorded_review_score: number | null;
810
+ /**
811
+ * 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.
812
+ * @deprecated
813
+ */
693
814
  recorded_signal_score: number | null;
694
815
  /** Persisted live suspicion score from the scorer. Null when the row has no persisted score. */
695
816
  suspicion_score: number | null;
@@ -737,6 +858,17 @@ export type LargeTradeHistoryMeta = {
737
858
  reason: string;
738
859
  };
739
860
  };
861
+ /** All present fields narrow large_trade_inserted_v2 delivery. Grade is observed at publication; ungraded trades do not match min_grade. An empty object matches every large trade. */
862
+ export type LargeTradeSubscriptionFilters = {
863
+ /** Raw provider condition ID or mkt_-prefixed market ID. */
864
+ condition_id?: string;
865
+ /** Polymarket wallet address; matching is case-insensitive. */
866
+ wallet?: string;
867
+ /** S is best; ungraded trades do not match. */
868
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
869
+ /** Positive USD notional as an exact decimal string. */
870
+ min_size_usd?: string;
871
+ };
740
872
  export type LeaderboardEntry = {
741
873
  id: string;
742
874
  address: string;
@@ -767,6 +899,68 @@ export type MarketCandles = {
767
899
  /** One entry per present provider token (YES first, then NO); empty when no tokens have been fetched yet. */
768
900
  outcomes: OutcomeCandles[];
769
901
  };
902
+ export type MarketFlow = {
903
+ market: {
904
+ id: string;
905
+ condition_id: string;
906
+ title: string;
907
+ slug: string | null;
908
+ category: string | null;
909
+ platform: string | null;
910
+ };
911
+ /** Outcome-aware flow from all tracked whale trades in the window, without a grade filter. BUY YES and SELL NO add net exposure; BUY NO and SELL YES subtract it. Gross buy/sell volumes count both outcomes. Top positions are separately graded. Direction uses unrounded net: negative is NO, otherwise YES; the zero tie-break is not conviction. Canonical; smart_money is a deprecated byte-identical alias. */
912
+ sharp_money: {
913
+ net_flow_usd: number;
914
+ direction: "YES" | "NO";
915
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
916
+ token_id: string | null;
917
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
918
+ large_trade_count?: number;
919
+ whale_trade_count: number;
920
+ buy_volume_usd: number;
921
+ sell_volume_usd: number;
922
+ top_positions: ({
923
+ id: string;
924
+ address: string;
925
+ username: string | null;
926
+ grade: string | null;
927
+ side: "YES" | "NO";
928
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
929
+ token_id: string | null;
930
+ size_usd: number;
931
+ })[];
932
+ /** Age of the oldest stored position snapshot behind top_positions: the minimum wallet sync clock over the positions this body publishes. The roster is a stored read rather than a live one, and graded wallets sit on different sync tiers, so this names how current the whole roster is; the response is no fresher than this timestamp. Null when the roster is empty or no published position carries a sync clock. It does not date net_flow_usd, the volumes or the trade counts, which come from large-trade event times. */
933
+ oldest_snapshot_as_of: string | null;
934
+ };
935
+ /**
936
+ * Deprecated alias of sharp_money; byte-identical and retained for backward compatibility.
937
+ * @deprecated
938
+ */
939
+ smart_money: {
940
+ net_flow_usd: number;
941
+ direction: "YES" | "NO";
942
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
943
+ token_id: string | null;
944
+ /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
945
+ large_trade_count?: number;
946
+ whale_trade_count: number;
947
+ buy_volume_usd: number;
948
+ sell_volume_usd: number;
949
+ top_positions: ({
950
+ id: string;
951
+ address: string;
952
+ username: string | null;
953
+ grade: string | null;
954
+ side: "YES" | "NO";
955
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
956
+ token_id: string | null;
957
+ size_usd: number;
958
+ })[];
959
+ /** Age of the oldest stored position snapshot behind top_positions: the minimum wallet sync clock over the positions this body publishes. The roster is a stored read rather than a live one, and graded wallets sit on different sync tiers, so this names how current the whole roster is; the response is no fresher than this timestamp. Null when the roster is empty or no published position carries a sync clock. It does not date net_flow_usd, the volumes or the trade counts, which come from large-trade event times. */
960
+ oldest_snapshot_as_of: string | null;
961
+ };
962
+ timeframe: string;
963
+ };
770
964
  export type MarketHolder = {
771
965
  /** Composite `pos_<wallet>:<condition_id>:<outcome_index>`, the same id `GET /api/v1/positions` gives this leg. */
772
966
  id: string;
@@ -862,65 +1056,6 @@ export type MarketHoldersTotals = {
862
1056
  yes_grades: MarketHoldersSideGrades;
863
1057
  no_grades: MarketHoldersSideGrades;
864
1058
  };
865
- export type MarketIntel = {
866
- market: {
867
- id: string;
868
- condition_id: string;
869
- title: string;
870
- slug: string | null;
871
- category: string | null;
872
- platform: string | null;
873
- };
874
- /** Outcome-aware flow from all tracked whale trades in the window, without a grade filter. BUY YES and SELL NO add net exposure; BUY NO and SELL YES subtract it. Gross buy/sell volumes count both outcomes. Top positions are separately graded. Direction uses unrounded net: negative is NO, otherwise YES; the zero tie-break is not conviction. Canonical; smart_money is a deprecated byte-identical alias. */
875
- sharp_money: {
876
- net_flow_usd: number;
877
- direction: "YES" | "NO";
878
- /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
879
- token_id: string | null;
880
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
881
- large_trade_count?: number;
882
- whale_trade_count: number;
883
- buy_volume_usd: number;
884
- sell_volume_usd: number;
885
- top_positions: ({
886
- id: string;
887
- address: string;
888
- username: string | null;
889
- grade: string | null;
890
- side: "YES" | "NO";
891
- /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
892
- token_id: string | null;
893
- size_usd: number;
894
- })[];
895
- /** Age of the oldest stored position snapshot behind top_positions: the minimum wallet sync clock over the positions this body publishes. The roster is a stored read rather than a live one, and graded wallets sit on different sync tiers, so this names how current the whole roster is; the response is no fresher than this timestamp. Null when the roster is empty or no published position carries a sync clock. It does not date net_flow_usd, the volumes or the trade counts, which come from large-trade event times. */
896
- oldest_snapshot_as_of: string | null;
897
- };
898
- /** Deprecated alias of sharp_money; byte-identical and retained for backward compatibility. */
899
- smart_money: {
900
- net_flow_usd: number;
901
- direction: "YES" | "NO";
902
- /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
903
- token_id: string | null;
904
- /** Canonical key since #16304 (Polymarket's noun is large trade); whale_trade_count is its deprecated spelling, emitted beside it with the same value. */
905
- large_trade_count?: number;
906
- whale_trade_count: number;
907
- buy_volume_usd: number;
908
- sell_volume_usd: number;
909
- top_positions: ({
910
- id: string;
911
- address: string;
912
- username: string | null;
913
- grade: string | null;
914
- side: "YES" | "NO";
915
- /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
916
- token_id: string | null;
917
- size_usd: number;
918
- })[];
919
- /** Age of the oldest stored position snapshot behind top_positions: the minimum wallet sync clock over the positions this body publishes. The roster is a stored read rather than a live one, and graded wallets sit on different sync tiers, so this names how current the whole roster is; the response is no fresher than this timestamp. Null when the roster is empty or no published position carries a sync clock. It does not date net_flow_usd, the volumes or the trade counts, which come from large-trade event times. */
920
- oldest_snapshot_as_of: string | null;
921
- };
922
- timeframe: string;
923
- };
924
1059
  export type MarketSearchResult = {
925
1060
  id: string;
926
1061
  condition_id: string;
@@ -1098,15 +1233,25 @@ export type PickOfTheDay = {
1098
1233
  position?: string;
1099
1234
  /** One-line summary of which side sharp money is backing. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof. */
1100
1235
  side_summary?: string;
1101
- /** Public V1 compatibility count of S/A smart-money wallets on the backed side. The first-party/internal current policy counts S/A/B; historical rows retain their frozen policy's count. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof. */
1236
+ /** Public V1 compatibility count of S/A sharp-money wallets on the backed side. The first-party/internal current policy counts S/A/B; historical rows retain their frozen policy's count. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof. Canonical key since #16308; smart_wallet_count is its deprecated spelling, emitted beside it with the same value. */
1237
+ sharp_wallet_count?: number;
1238
+ /**
1239
+ * Deprecated spelling of sharp_wallet_count, emitted beside it with the same value and never removed. Public V1 compatibility count of S/A sharp-money wallets on the backed side. The first-party/internal current policy counts S/A/B; historical rows retain their frozen policy's count. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof.
1240
+ * @deprecated
1241
+ */
1102
1242
  smart_wallet_count?: number;
1103
- /** Best public V1-compatible S/A smart-money grade on the backed side. The first-party/internal current policy can select B, but a current B-only grade is omitted by the stable V1 adapter. Historical rows retain their frozen policy's grade. A current-day published pick with pending legacy proof, unknown-future proof, or structurally invalid current-policy proof returns 503 before this success schema is served. Resolved legacy proof remains readable on both current-day and archive/history responses. */
1243
+ /** Best public V1-compatible S/A sharp-money grade on the backed side. The first-party/internal current policy can select B, but a current B-only grade is omitted by the stable V1 adapter. Historical rows retain their frozen policy's grade. A current-day published pick with pending legacy proof, unknown-future proof, or structurally invalid current-policy proof returns 503 before this success schema is served. Resolved legacy proof remains readable on both current-day and archive/history responses. */
1104
1244
  top_grade?: string;
1105
1245
  /** Deprecated (#7170): no longer populated for picks selected on/after the calibration-edge change; omitted (absent) for new picks (the field uses skip_serializing_if, so a null value is dropped from the JSON rather than serialized as null). Permanently frozen-legacy -- retained for historical picks, with no removal or replacement planned, so no v2 is implied. Historical picks may still carry a value. Legacy meaning: category win-rate edge as a fraction (the backed-side cohort's win rate in this category minus the non-market-maker category baseline, e.g. 0.09 = +9 points), paired with category_edge_sample. */
1106
1246
  category_edge_pct?: number;
1107
1247
  /** Deprecated (#7170): no longer populated for picks selected on/after the calibration-edge change; omitted (absent) for new picks (the field uses skip_serializing_if, so a null value is dropped from the JSON rather than serialized as null). Permanently frozen-legacy -- retained for historical picks, with no removal or replacement planned, so no v2 is implied. Historical picks may still carry a value. Legacy meaning: pooled count of resolved markets behind category_edge_pct (the headline's n). */
1108
1248
  category_edge_sample?: number;
1109
- /** Recency-weighted graded-flow magnitude in USD; omitted when <= 0. */
1249
+ /** Recency-weighted graded-flow magnitude in USD; omitted when <= 0. Canonical key since #16308; smart_usd is its deprecated spelling, emitted beside it with the same value. */
1250
+ sharp_usd?: number;
1251
+ /**
1252
+ * Deprecated spelling of sharp_usd, emitted beside it with the same value and never removed. Recency-weighted graded-flow magnitude in USD; omitted when <= 0.
1253
+ * @deprecated
1254
+ */
1110
1255
  smart_usd?: number;
1111
1256
  /** Frozen pre-game probability (0..1) for the backed side, written once at publication. It is the Polymarket CLOB order book midpoint at release, not an executed fill: a buyer lifts the ask, so a subscriber's own entry is usually a little worse than this price. */
1112
1257
  backed_price?: number;
@@ -1190,15 +1335,15 @@ export type PickOfTheDay = {
1190
1335
  lane_probability_source?: "p";
1191
1336
  };
1192
1337
  trust?: PickTrust;
1193
- /** Public V1 S/A compatibility count on the backed side (equals the adapted smart_wallet_count). The first-party/internal current policy counts S/A/B. Historical rows retain their frozen policy's count. */
1338
+ /** Public V1 S/A compatibility count on the backed side (equals the adapted sharp_wallet_count). The first-party/internal current policy counts S/A/B. Historical rows retain their frozen policy's count. */
1194
1339
  traders?: number;
1195
- /** Raw backed-side sharp-money USD frozen at generation. This is the Sharp USD value, not the recency-weighted smart_usd which decays. Omitted on current public V1 rows when the B-inclusive value has no reconstructible S/A equivalent. */
1340
+ /** Raw backed-side sharp-money USD frozen at generation. This is the Sharp USD value, not the recency-weighted sharp_usd which decays. Omitted on current public V1 rows when the B-inclusive value has no reconstructible S/A equivalent. */
1196
1341
  backed_sharp_usd?: number;
1197
1342
  /** Bounded S/A compatibility projection of the frozen sharp-money holders on the backed side. Current full payloads expose the complete S/A/B roster in display_holders; historical rows can retain their earlier frozen shape. */
1198
1343
  holders?: PickHolder[];
1199
1344
  /** Full-only complete provider-confirmed S/A/B holder roster for the current Pick of the Day backing policy. Omitted for teaser, no-pick, and historical rows whose frozen holder proof predates this policy. Each entry may additionally carry `category_win_rate` / `category_win_rate_status`: the wallet's win rate in the pick's canonical `category`, stamped at serve time from the current category read model (the same annotation the sports sharp-money chips carry). The bounded `holders` compatibility projection never carries these fields. */
1200
1345
  display_holders?: PickHolder[];
1201
- /** Exact S/A smart-money proof count on the backed side. The current display_holders roster can be longer because it also carries B-grade smart-money holders. */
1346
+ /** Exact S/A sharp-money proof count on the backed side. The current display_holders roster can be longer because it also carries B-grade sharp-money holders. */
1202
1347
  holder_count?: number;
1203
1348
  /** Optional editorial note attached to the pick. */
1204
1349
  editorial_note?: string;
@@ -1263,7 +1408,7 @@ export type PickOfTheDayArchiveEntry = {
1263
1408
  image_url?: string;
1264
1409
  /** The backed side's outcome label. Omitted for a still-pending pick when the request is not from an authenticated Pro key. */
1265
1410
  pick_outcome_label?: string;
1266
- /** Best public V1-compatible S/A smart-money grade on the backed side; a current B-only grade is omitted by the stable V1 adapter, while historical rows retain their frozen policy's grade. Omitted when no smart-money wallet backs the pick, when a pending legacy proof has not yet upgraded, or when the stored holder policy is unknown-future or structurally invalid. Resolved legacy history remains supported. */
1411
+ /** Best public V1-compatible S/A sharp-money grade on the backed side; a current B-only grade is omitted by the stable V1 adapter, while historical rows retain their frozen policy's grade. Omitted when no sharp-money wallet backs the pick, when a pending legacy proof has not yet upgraded, or when the stored holder policy is unknown-future or structurally invalid. Resolved legacy history remains supported. */
1267
1412
  top_grade?: string;
1268
1413
  /** Settlement outcome of the backed side; 'pending' until the market resolves. */
1269
1414
  outcome: "pending" | "win" | "loss" | "void";
@@ -1591,6 +1736,8 @@ export type Position = {
1591
1736
  cash_pnl?: number;
1592
1737
  /** Closed-leg P&L rolled up (Polymarket `realizedPnl`). */
1593
1738
  realized_pnl?: number;
1739
+ /** Additive lossless source atoms for the display-safe position fields. Parse every `value` with decimal-safe arithmetic; never recover exact values from the numeric twins. */
1740
+ exact?: PositionExact;
1594
1741
  /** Max updated_at across mirror legs for this pair. */
1595
1742
  last_reconciled_at?: string;
1596
1743
  /** Backend-computed staleness bucket derived from last_reconciled_at. */
@@ -1623,6 +1770,17 @@ export type Position = {
1623
1770
  end_date?: string;
1624
1771
  };
1625
1772
  };
1773
+ /** Lossless position atoms from `wallet_positions`. `shares` and `current_value_usd` are required when this object is present; other source values are omitted when the mirror has no verified value. */
1774
+ export type PositionExact = {
1775
+ shares: ExactDecimal;
1776
+ cost_basis_usd?: ExactDecimal;
1777
+ /** Exact derived price: `wallet_positions.cost_basis_usd / wallet_positions.shares`. */
1778
+ avg_price?: ExactDecimal;
1779
+ current_value_usd: ExactDecimal;
1780
+ initial_value_usd?: ExactDecimal;
1781
+ cash_pnl?: ExactDecimal;
1782
+ realized_pnl?: ExactDecimal;
1783
+ };
1626
1784
  export type PositionTimelineEvent = {
1627
1785
  /** Prefixed ID (pe_...). */
1628
1786
  id: string;
@@ -1679,7 +1837,10 @@ export type PreGameSide = {
1679
1837
  side_share: number | null;
1680
1838
  /** Polymarket condition id. */
1681
1839
  condition_id: string;
1682
- /** UTC time at which the immutable signal snapshot was computed. Every row from one snapshot shares this value; it is not provider market creation time and is not rewritten at request time. Deprecated (#16310): `ranked_at` is the canonical spelling and carries the same value; this key stays on the wire. */
1840
+ /**
1841
+ * UTC time at which the immutable signal snapshot was computed. Every row from one snapshot shares this value; it is not provider market creation time and is not rewritten at request time. Deprecated (#16310): `ranked_at` is the canonical spelling and carries the same value; this key stays on the wire.
1842
+ * @deprecated
1843
+ */
1683
1844
  signal_created_at: string;
1684
1845
  /** Polymarket CLOB token id (ERC1155 asset id, decimal string) for the PILED outcome; null when unavailable. */
1685
1846
  token_id: string | null;
@@ -1691,7 +1852,10 @@ export type PreGameSide = {
1691
1852
  event_slug: string | null;
1692
1853
  /** Kickoff (UTC). In the future at SNAPSHOT time and within the requested horizon; because the response is served from a shared snapshot cached up to the ~180s TTL, a served kickoff can be up to ~180s in the past relative to the response time. Not a live guarantee that the game has not yet started. */
1693
1854
  game_start_time: string | null;
1694
- /** Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. Deprecated (#16310): `side` is the canonical spelling and carries the same value; this key stays on the wire. */
1855
+ /**
1856
+ * Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. Deprecated (#16310): `side` is the canonical spelling and carries the same value; this key stays on the wire.
1857
+ * @deprecated
1858
+ */
1695
1859
  piled_side: string | null;
1696
1860
  /** Provider binary-column selector: 0 selects outcome_yes/token_id_yes; 1 selects outcome_no/token_id_no. It does not identify home/away or a participant. Use piled_side together with title/event context for display. */
1697
1861
  piled_outcome_index: number;
@@ -1709,13 +1873,19 @@ export type PreGameSide = {
1709
1873
  graded_holders: number;
1710
1874
  /** Best grade present on the piled side; null when none. */
1711
1875
  top_grade: "S" | "A" | "B" | null;
1712
- /** Canonical sharp-money score (yes_usd - no_usd)/(yes_usd + no_usd) in [-1, 1] (piled-yes positive, piled-no negative); a lower-order ranking tiebreak (after directional_rank_score and conviction_score). Deprecated (#16310): `side_share` is the canonical spelling and carries the same value; this key stays on the wire. */
1876
+ /**
1877
+ * Canonical sharp-money score (yes_usd - no_usd)/(yes_usd + no_usd) in [-1, 1] (piled-yes positive, piled-no negative); a lower-order ranking tiebreak (after directional_rank_score and conviction_score). Deprecated (#16310): `side_share` is the canonical spelling and carries the same value; this key stays on the wire.
1878
+ * @deprecated
1879
+ */
1713
1880
  smart_score: number | null;
1714
1881
  /** Market volume (USD). */
1715
1882
  volume: number | null;
1716
1883
  /** Aggregate recent flow direction on the market; null when unavailable. */
1717
1884
  net_side: "BUY" | "SELL" | null;
1718
- /** Grade-weighted pile score (5*s + 4*a + 3*b) * sharp_pct; the raw conviction input to the ranking (see directional_rank_score). Deprecated (#16310): `backing_score` is the canonical spelling and carries the same value; this key stays on the wire. */
1885
+ /**
1886
+ * Grade-weighted pile score (5*s + 4*a + 3*b) * sharp_pct; the raw conviction input to the ranking (see directional_rank_score). Deprecated (#16310): `backing_score` is the canonical spelling and carries the same value; this key stays on the wire.
1887
+ * @deprecated
1888
+ */
1719
1889
  conviction_score: number;
1720
1890
  /** Piled-side graded holders read one-way: their fresh open legs across the signal game's markets (cross-market within the one game; moneyline+spread family only) all back the same team, or, when the market's holder scan was complete, Polymarket's currentValue shows no opposite leg on this market worth 10% of the backed leg and no fresh leg opposes it. Null when the directional read was not computed (no groupable game, no holder-level data on this ranking path, or the enrichment read failed) or classified nobody. */
1721
1891
  one_way_holder_count: number | null;
@@ -1789,7 +1959,10 @@ export type PreGameSideObservation = {
1789
1959
  cohort: "wider_holder" | "in_play" | "emerging_pile";
1790
1960
  /** Always true. This row must not be routed to an order executor. */
1791
1961
  observation_only: true;
1792
- /** Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. Deprecated (#16310): `side` is the canonical spelling and carries the same value; this key stays on the wire. */
1962
+ /**
1963
+ * Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. Deprecated (#16310): `side` is the canonical spelling and carries the same value; this key stays on the wire.
1964
+ * @deprecated
1965
+ */
1793
1966
  piled_side: string | null;
1794
1967
  /** Provider binary-column selector: 0 selects outcome_yes/token_id_yes; 1 selects outcome_no/token_id_no. It does not identify home/away or a participant. Use piled_side together with title/event context for display. */
1795
1968
  piled_outcome_index: 0 | 1;
@@ -1805,11 +1978,17 @@ export type PreGameSideObservation = {
1805
1978
  /** Piled-side S/A/B holder count. */
1806
1979
  graded_holders: number;
1807
1980
  top_grade: "S" | "A" | "B";
1808
- /** Canonical signed holder-pile score. Deprecated (#16310): `side_share` is the canonical spelling and carries the same value; this key stays on the wire. */
1981
+ /**
1982
+ * Canonical signed holder-pile score. Deprecated (#16310): `side_share` is the canonical spelling and carries the same value; this key stays on the wire.
1983
+ * @deprecated
1984
+ */
1809
1985
  smart_score: number;
1810
1986
  /** Strictly positive stored market volume in USD. Missing, zero, or non-finite volume terminates as invalid_market and is never emitted as an observation. */
1811
1987
  volume: number;
1812
- /** Grade-weighted holder-pile score before directional enrichment. Deprecated (#16310): `backing_score` is the canonical spelling and carries the same value; this key stays on the wire. */
1988
+ /**
1989
+ * Grade-weighted holder-pile score before directional enrichment. Deprecated (#16310): `backing_score` is the canonical spelling and carries the same value; this key stays on the wire.
1990
+ * @deprecated
1991
+ */
1813
1992
  conviction_score: number;
1814
1993
  /** Whether the provider holder page came from the shared cache or a live provider read. */
1815
1994
  provider_read_source: "cached" | "live";
@@ -1967,9 +2146,9 @@ export type ResponseMeta = {
1967
2146
  ranking_generation?: number;
1968
2147
  /** Authoritative RFC3339 timestamp from cache_generations.updated_at for ranking_generation. It is read in the same repeatable-read snapshot as the leaderboard rows and is not request time, cache write time, or row insertion order. */
1969
2148
  ranking_as_of?: string;
1970
- /** Which path produced the team-directional read on this response. Only present on endpoints that compute one (today: GET /api/v1/sports-edge-signals). "live" means the read RAN. "degraded" means it FAILED, so nothing was measured and the ranking fell back to raw conviction. The flag describes the READ, not its consequence: a read that ran and found nothing groupable also leaves the directional fields null, and that is honestly "live" -- the per-signal nulls already say "nothing to enrich here", so this snapshot-level flag carries only what they cannot, namely whether the read ran at all. A degraded response is cached on the shorter degraded TTL so it self-heals. Reported SEPARATELY from ranking_source because the two degradations are independent -- a smart-money DB miss weakens the ranking DATA, a directional failure removes a ranking WEIGHT -- and a consumer down-weighting a degraded response needs to know which input it lost. Omitted on endpoints that compute no directional read. */
2149
+ /** Which path produced the team-directional read on this response. Only present on endpoints that compute one (today: GET /api/v1/sports-edge-signals). "live" means the read RAN. "degraded" means it FAILED, so nothing was measured and the ranking fell back to raw conviction. The flag describes the READ, not its consequence: a read that ran and found nothing groupable also leaves the directional fields null, and that is honestly "live" -- the per-signal nulls already say "nothing to enrich here", so this snapshot-level flag carries only what they cannot, namely whether the read ran at all. A degraded response is cached on the shorter degraded TTL so it self-heals. Reported SEPARATELY from ranking_source because the two degradations are independent -- a sharp-money DB miss weakens the ranking DATA, a directional failure removes a ranking WEIGHT -- and a consumer down-weighting a degraded response needs to know which input it lost. Omitted on endpoints that compute no directional read. */
1971
2150
  directional_source?: "live" | "degraded";
1972
- /** Which ranking-data path produced this response. Only present on endpoints that can degrade a ranking (today: GET /api/v1/sports-edge-signals). "live" is the normal path (the current holder pile from the provider batch); "db_only" is the degraded fallback (a truthful but weaker trader_markets ranking) served when the live sharp-money ranking batch is unavailable (a smart-money DB read failure, not a Polymarket outage) and cached on a shorter TTL, so a consumer can down-weight or skip it. Omitted on endpoints that never degrade. */
2151
+ /** Which ranking-data path produced this response. Only present on endpoints that can degrade a ranking (today: GET /api/v1/sports-edge-signals). "live" is the normal path (the current holder pile from the provider batch); "db_only" is the degraded fallback (a truthful but weaker trader_markets ranking) served when the live sharp-money ranking batch is unavailable (a sharp-money DB read failure, not a Polymarket outage) and cached on a shorter TTL, so a consumer can down-weight or skip it. Omitted on endpoints that never degrade. */
1973
2152
  ranking_source?: "live" | "db_only";
1974
2153
  /** Whole filtered snapshot category-evidence status before pagination. Operational live always remains partial source coverage. */
1975
2154
  category_skill_source?: "live" | "partial" | "degraded" | "unavailable";
@@ -2032,7 +2211,10 @@ export type SmartMoneyFlowMarket = {
2032
2211
  buy_volume_usd: number;
2033
2212
  sell_volume_usd: number;
2034
2213
  };
2035
- /** Deprecated alias of sharp_money; byte-identical and retained for backward compatibility. */
2214
+ /**
2215
+ * Deprecated alias of sharp_money; byte-identical and retained for backward compatibility.
2216
+ * @deprecated
2217
+ */
2036
2218
  smart_money: {
2037
2219
  net_flow_usd: number;
2038
2220
  direction: "YES" | "NO";
@@ -2114,6 +2296,10 @@ export type Trader = {
2114
2296
  /** Hot-streak tier (trailing-7d cross-sectional percentile); a separate axis from the all-time grade. Omitted when there is no recent activity. */
2115
2297
  streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
2116
2298
  score?: number;
2299
+ /** Capital-normalized forecasting score: the cohort percentile (0-100) of the EB-shrunk calibration edge. Omitted when the forecasting signal is unavailable; never replaced with zero. */
2300
+ forecast_score?: number;
2301
+ /** Share of forecast_score supported by the trader's own resolved-market record rather than the cohort prior: n / (n + 30). Omitted when forecast_score is unavailable. */
2302
+ forecast_evidence?: number;
2117
2303
  rank?: number;
2118
2304
  pnl: {
2119
2305
  total?: number;
@@ -2124,13 +2310,17 @@ export type Trader = {
2124
2310
  last_7d?: number;
2125
2311
  /** 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. */
2126
2312
  last_30d?: number;
2313
+ /** Additive lossless counterpart. Omitted when the trusted native realized-P&L source is unavailable; existing numeric fields keep their display-safe v1 semantics. */
2314
+ exact?: TraderPnlExact;
2127
2315
  };
2128
2316
  stats: {
2129
2317
  markets_traded?: number;
2130
2318
  win_rate?: number;
2131
2319
  daily_win_rate?: number;
2132
- /** Full-history both-sides USD cash volume from Polymarket user-volume. Omitted without a verified observation; never leaderboard shares. Volume freshness is unknown in this DTO and does not use synced_at. */
2320
+ /** 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. */
2133
2321
  total_volume?: number;
2322
+ /** Additive lossless counterpart to `total_volume`. Omitted when the verified provider observation is unavailable. */
2323
+ exact?: TraderStatsExact;
2134
2324
  };
2135
2325
  strategy?: {
2136
2326
  strategy_type?: string;
@@ -2164,6 +2354,8 @@ export type Trader = {
2164
2354
  synced_at?: string;
2165
2355
  /** synced, unknown, or pending. */
2166
2356
  sync_status?: string;
2357
+ /** Data age and coverage for this trader body. Always present. Its five groups are sync (traders.last_synced, covering pnl.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). 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. */
2358
+ data_quality: DataQuality;
2167
2359
  /** Field-level trust metadata. Present only when expand=trust or expand[]=trust is requested. */
2168
2360
  trust?: TraderTrust;
2169
2361
  /** 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. */
@@ -2248,22 +2440,56 @@ export type TraderEsportsGameRecord = {
2248
2440
  /** The same rule as the parent record: measured when decided cleared min_decided_for_win_rate, not_enough_data when the counts are real but the sample is under the floor. A chip on a market in this game shows this row's rate when it is measured and the Esports bucket's otherwise. */
2249
2441
  status: "measured" | "not_enough_data";
2250
2442
  };
2443
+ export type TraderExportArtifactManifest = {
2444
+ /** Version of the artifact manifest contract. */
2445
+ manifest_version: string;
2446
+ /** Serialization used for the decompressed content. */
2447
+ format: "json" | "ndjson" | "csv";
2448
+ /** Stable schema identifier for the selected serialization. */
2449
+ schema_version: "trader-export-json-v1" | "trader-export-ndjson-v1" | "trader-export-csv-v1";
2450
+ /** Sections represented by the artifact. JSON and NDJSON carry the full envelope and trades; CSV carries trade rows only. */
2451
+ coverage: "full_envelope_and_trades" | "trades_only";
2452
+ generation: TraderExportGeneration;
2453
+ /** Number of trade rows written. */
2454
+ row_count: number;
2455
+ /** Exact byte count of the decompressed content stream clients receive. */
2456
+ content_size_bytes: number;
2457
+ /** Lowercase SHA-256 of the decompressed content bytes. */
2458
+ content_sha256: string;
2459
+ /** Exact byte count of the gzip-compressed bytes stored by the object provider. */
2460
+ compressed_size_bytes: number;
2461
+ /** Lowercase SHA-256 of the stored gzip bytes; the multipart ETag is not used as this checksum. */
2462
+ compressed_sha256: string;
2463
+ };
2464
+ export type TraderExportCategoryWatermark = {
2465
+ source: string;
2466
+ coverage: string;
2467
+ publication_fence: string | null;
2468
+ data_as_of: string | null;
2469
+ };
2470
+ export type TraderExportGeneration = {
2471
+ /** Opaque generation identity selected for the coherent read snapshot. */
2472
+ id: string;
2473
+ selected_at: string;
2474
+ consistency: "repeatable_read";
2475
+ source_watermarks: TraderExportSourceWatermarks;
2476
+ };
2251
2477
  export type TraderExportJob = {
2252
2478
  object: "trader_export_job";
2253
2479
  data: {
2254
2480
  job_id: number;
2255
- /** 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. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed and expired rows stay readable for 48 hours, then the job answers 404. */
2256
- status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired";
2481
+ /** 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. */
2482
+ status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
2257
2483
  format: "json" | "ndjson" | "csv";
2258
2484
  total_trades: number | null;
2259
2485
  processed_trades: number | null;
2260
2486
  file_size: number | null;
2261
2487
  error: string | null;
2262
- /** True when status never changes again (ready, failed, expired). Stop polling. */
2488
+ /** True when status never changes again (ready, failed, expired, cancelled). Stop polling. */
2263
2489
  terminal: boolean;
2264
2490
  /** What to do next: poll the status route after poll_after_s, follow the download route, or submit a new export. Published beside status so a status value added later does not strand a client. */
2265
2491
  next_action: "poll" | "download" | "resubmit";
2266
- /** Seconds to wait before polling again. Absent when terminal. 5 while queued or running; 300 while reconcile_required, the cadence that state can change at. */
2492
+ /** Seconds to wait before polling again. Absent when terminal. 5 while queued, running or cancel_requested; 300 while reconcile_required, the cadence that state can change at. */
2267
2493
  poll_after_s?: number;
2268
2494
  created_at: string;
2269
2495
  /** When the worker last claimed the job; null while queued. */
@@ -2277,22 +2503,42 @@ export type TraderExportJob = {
2277
2503
  expired_at: string | null;
2278
2504
  /** What the file is a snapshot of: the trader's served-data clock (the latest position refresh, else the last completed sync) when the file was written; the same value as export_metadata.data_as_of inside the file. null until the file is written, or when the trader had neither. Read this, not ready_at, to decide whether a reused job is fresh enough; submit with fresh=true for a newer snapshot. */
2279
2505
  data_as_of: string | null;
2506
+ /** When the owner asked to cancel the job; null otherwise. Set on every cancelled job, including one cancelled while queued. While status is cancel_requested this is the instant the worker was asked to stop. */
2507
+ cancel_requested_at: string | null;
2508
+ /** When the job reached cancelled; null until then. */
2509
+ cancelled_at: string | null;
2280
2510
  /** Worker claims so far. */
2281
2511
  attempt: number;
2282
2512
  /** The job fails when attempt reaches this. */
2283
2513
  max_attempts: number;
2284
2514
  /** Present only while status is ready: the stored object's identity, so a client can check the download it receives. */
2285
2515
  artifact?: {
2516
+ /** Stable identity for this completed export artifact; unchanged when a temporary download URL is renewed. */
2517
+ artifact_id: string;
2286
2518
  /** The storage ETag of the object. */
2287
2519
  etag: string | null;
2288
2520
  /** Bytes on the wire (gzip); file_size is the decompressed size. */
2289
2521
  compressed_size_bytes: number | null;
2290
2522
  content_type: "application/json" | "application/x-ndjson" | "text/csv";
2291
2523
  content_encoding: "gzip";
2524
+ /** Immutable manifest for artifacts generated with manifest support; null on historical artifacts written before this contract. */
2525
+ manifest: TraderExportArtifactManifest | null;
2292
2526
  };
2293
2527
  };
2294
2528
  meta: ResponseMeta;
2295
2529
  };
2530
+ export type TraderExportPnlWatermark = {
2531
+ source: string;
2532
+ coverage: string;
2533
+ revision: number | null;
2534
+ observed_at: string | null;
2535
+ };
2536
+ export type TraderExportPositionWatermark = {
2537
+ source: string;
2538
+ coverage: string;
2539
+ generation: number | null;
2540
+ data_as_of: string | null;
2541
+ };
2296
2542
  export type TraderExportSnapshot = {
2297
2543
  address: string;
2298
2544
  generated_at: string;
@@ -2302,6 +2548,49 @@ export type TraderExportSnapshot = {
2302
2548
  counts: ExportCounts;
2303
2549
  large_export_policy: LargeExportPolicy;
2304
2550
  };
2551
+ export type TraderExportSourceWatermarks = {
2552
+ positions: TraderExportPositionWatermark;
2553
+ pnl: TraderExportPnlWatermark;
2554
+ categories: TraderExportCategoryWatermark;
2555
+ trades: TraderExportTradeWatermark;
2556
+ };
2557
+ export type TraderExportTradeWatermark = {
2558
+ source: string;
2559
+ coverage: string;
2560
+ rows: number;
2561
+ first_activity_date: string | null;
2562
+ };
2563
+ export type TraderGradeAt = {
2564
+ /** Prefixed trader id (trd_<wallet>). */
2565
+ id: string;
2566
+ /** Resolved wallet address, lowercased. */
2567
+ address: string;
2568
+ /** Requested event or decision time. */
2569
+ as_of: string;
2570
+ /** graded has a proven grade; ungraded is a proven null grade; unknown has no valid historical observation. */
2571
+ status: "graded" | "ungraded" | "unknown";
2572
+ /** Grade only when status is graded; null otherwise. */
2573
+ grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
2574
+ /** First proven visibility instant for this trader. Null when no observation exists. Earlier times remain unknown. */
2575
+ available_from: string | null;
2576
+ /** Proof row when status is graded or ungraded. Null when history is unknown. */
2577
+ observation: {
2578
+ /** Immutable grade_forward_history observation id. */
2579
+ id: number;
2580
+ /** Previous immutable observation id when retained. A later grade change supersedes that observation but never erases it; this link does not assert why the grade changed. */
2581
+ previous_observation_id: number | null;
2582
+ /** Lower bound: the grade writer had started the transition at this instant. */
2583
+ observed_at: string;
2584
+ /** Upper bound: a later snapshot confirmed the observation was committed. This is not an exact commit timestamp. */
2585
+ published_by: string;
2586
+ /** Writer-proven model family, such as grading-v4. Null when unknown. */
2587
+ model_version: string | null;
2588
+ /** Exact writer build SHA when recorded. Null on old and non-model observations. */
2589
+ model_build_sha: string | null;
2590
+ /** Database-clock upper bound on when the grading pass read its cohort inputs. Not the event time or source freshness of every input; null when unknown. */
2591
+ source_observed_by: string | null;
2592
+ } | null;
2593
+ };
2305
2594
  /** 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. */
2306
2595
  export type TraderPnl = {
2307
2596
  /** Prefixed trader ID (`trd_...`). */
@@ -2414,6 +2703,16 @@ export type TraderPnl = {
2414
2703
  drawdown: number;
2415
2704
  }[];
2416
2705
  };
2706
+ /** Lossless counterparts for trader P&L values. The object is omitted when no trusted native realized-P&L snapshot is available. */
2707
+ export type TraderPnlExact = {
2708
+ /** 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. */
2709
+ realized: ExactDecimal;
2710
+ };
2711
+ /** Lossless counterparts for trader statistics. The object is omitted when the verified provider observation is unavailable. */
2712
+ export type TraderStatsExact = {
2713
+ /** Full-history both-sides Polymarket user-volume atom from the verified `trader_usd_volume` observation. */
2714
+ total_volume: ExactDecimal;
2715
+ };
2417
2716
  /** Field-level trust metadata returned only when GET /api/v1/trader/{address} includes expand=trust. */
2418
2717
  export type TraderTrust = {
2419
2718
  total_pnl: TrustMetadata;
@@ -2425,6 +2724,8 @@ export type TraderTrust = {
2425
2724
  total_volume: TrustMetadata;
2426
2725
  grade: TrustMetadata;
2427
2726
  score: TrustMetadata;
2727
+ forecast_score: TrustMetadata;
2728
+ forecast_evidence: TrustMetadata;
2428
2729
  rank: TrustMetadata;
2429
2730
  streak_tier: TrustMetadata;
2430
2731
  strategy: TrustMetadata;
@@ -2505,6 +2806,7 @@ export type UpdateWebhookRequest = {
2505
2806
  /** Replacement public HTTPS callback URL on the default port 443, validated and checked for uniqueness exactly like the create url. HTTPS scheme/host case, trailing DNS dots and port 443 normalize; path/query case is preserved. Changing it resets status to pending_verification and returns a new verification token; the new destination must pass the verification challenge before deliveries resume. */
2506
2807
  url?: string;
2507
2808
  event_types?: WebhookEventType[];
2809
+ trade_filters?: LargeTradeSubscriptionFilters;
2508
2810
  enabled?: boolean;
2509
2811
  };
2510
2812
  export type Usage = {
@@ -2579,6 +2881,7 @@ export type WebhookEndpoint = {
2579
2881
  name: string;
2580
2882
  url: string;
2581
2883
  event_types: WebhookEventType[];
2884
+ trade_filters: LargeTradeSubscriptionFilters;
2582
2885
  status: WebhookStatus;
2583
2886
  verified_at: string | null;
2584
2887
  verification_token_expires_at: string;
@@ -2591,7 +2894,7 @@ export type WebhookEndpoint = {
2591
2894
  signing_secret?: string;
2592
2895
  verification?: WebhookVerification;
2593
2896
  };
2594
- /** 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 (whale_trades_inserted, wallet_grade_changed, suspicious_trade_flagged, insider_radar_flag_raised, smart_money_flow_detected) only deliver to API keys on an active Pro subscription. suspicious_trade_flagged and insider_radar_flag_raised are two spellings of one event: either one subscribes, and an endpoint receives deliveries under the spelling it registered. */
2897
+ /** 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. */
2595
2898
  export type WebhookEventDescriptor = {
2596
2899
  id: WebhookEventType;
2597
2900
  /** One-line description of when the event fires. */
@@ -2601,7 +2904,7 @@ export type WebhookEventDescriptor = {
2601
2904
  /** active: the event has a firing producer callsite. dormant: advertised and subscribable, but does not yet enqueue any delivery. */
2602
2905
  status: "active" | "dormant";
2603
2906
  };
2604
- export type WebhookEventType = "whale_trades_inserted" | "live_sports_updated" | "whale_trader_synced" | "large_positions_updated" | "wallet_grade_changed" | "suspicious_trade_flagged" | "insider_radar_flag_raised" | "smart_money_flow_detected";
2907
+ export type WebhookEventType = "large_trade_inserted_v2" | "large_trades_inserted" | "whale_trades_inserted" | "live_sports_updated" | "trader_synced" | "whale_trader_synced" | "large_positions_updated" | "wallet_grade_changed" | "suspicious_trade_flagged" | "insider_radar_flag_raised" | "sharp_money_flow_detected" | "smart_money_flow_detected" | "export_job_ready" | "export_job_failed" | "export_job_expired" | "export_job_cancelled";
2605
2908
  export type WebhookRetryPolicy = {
2606
2909
  max_attempts: 8;
2607
2910
  terminal_status: "dead_letter";
@@ -2629,8 +2932,58 @@ export type WebhookVerification = {
2629
2932
  */
2630
2933
  export interface OperationData {
2631
2934
  activateWebhookSecret: WebhookEndpoint;
2632
- batchGetMarketIntel: BatchMarketIntelItem[];
2935
+ batchGetMarketFlow: BatchMarketFlowItem[];
2936
+ batchGetMarketIntel: BatchMarketFlowItem[];
2633
2937
  batchGetTraders: BatchTraderItem[];
2938
+ cancelTraderExport: {
2939
+ job_id: number;
2940
+ /** 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. */
2941
+ status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
2942
+ format: "json" | "ndjson" | "csv";
2943
+ total_trades: number | null;
2944
+ processed_trades: number | null;
2945
+ file_size: number | null;
2946
+ error: string | null;
2947
+ /** True when status never changes again (ready, failed, expired, cancelled). Stop polling. */
2948
+ terminal: boolean;
2949
+ /** What to do next: poll the status route after poll_after_s, follow the download route, or submit a new export. Published beside status so a status value added later does not strand a client. */
2950
+ next_action: "poll" | "download" | "resubmit";
2951
+ /** Seconds to wait before polling again. Absent when terminal. 5 while queued, running or cancel_requested; 300 while reconcile_required, the cadence that state can change at. */
2952
+ poll_after_s?: number;
2953
+ created_at: string;
2954
+ /** When the worker last claimed the job; null while queued. */
2955
+ started_at: string | null;
2956
+ /** When the file became downloadable. null before ready, and on jobs finalized before this field existed. */
2957
+ ready_at: string | null;
2958
+ failed_at: string | null;
2959
+ /** The retention window: 24 hours from submit. A ready file downloads until this instant; a job that has not reached ready by it fails. A reused job (200 on submit) keeps its original window. */
2960
+ expires_at: string;
2961
+ /** When the job became expired; null until then. */
2962
+ expired_at: string | null;
2963
+ /** What the file is a snapshot of: the trader's served-data clock (the latest position refresh, else the last completed sync) when the file was written; the same value as export_metadata.data_as_of inside the file. null until the file is written, or when the trader had neither. Read this, not ready_at, to decide whether a reused job is fresh enough; submit with fresh=true for a newer snapshot. */
2964
+ data_as_of: string | null;
2965
+ /** When the owner asked to cancel the job; null otherwise. Set on every cancelled job, including one cancelled while queued. While status is cancel_requested this is the instant the worker was asked to stop. */
2966
+ cancel_requested_at: string | null;
2967
+ /** When the job reached cancelled; null until then. */
2968
+ cancelled_at: string | null;
2969
+ /** Worker claims so far. */
2970
+ attempt: number;
2971
+ /** The job fails when attempt reaches this. */
2972
+ max_attempts: number;
2973
+ /** Present only while status is ready: the stored object's identity, so a client can check the download it receives. */
2974
+ artifact?: {
2975
+ /** Stable identity for this completed export artifact; unchanged when a temporary download URL is renewed. */
2976
+ artifact_id: string;
2977
+ /** The storage ETag of the object. */
2978
+ etag: string | null;
2979
+ /** Bytes on the wire (gzip); file_size is the decompressed size. */
2980
+ compressed_size_bytes: number | null;
2981
+ content_type: "application/json" | "application/x-ndjson" | "text/csv";
2982
+ content_encoding: "gzip";
2983
+ /** Immutable manifest for artifacts generated with manifest support; null on historical artifacts written before this contract. */
2984
+ manifest: TraderExportArtifactManifest | null;
2985
+ };
2986
+ };
2634
2987
  createMcpJsonRpcResponse: {
2635
2988
  jsonrpc: "2.0";
2636
2989
  id: string | number | null;
@@ -2658,6 +3011,7 @@ export interface OperationData {
2658
3011
  scopes: string[] | null;
2659
3012
  };
2660
3013
  getApiDiscovery: ApiDiscovery;
3014
+ getCoverage: Platforms;
2661
3015
  getDailyReportSnapshot: ReportSnapshot;
2662
3016
  getEventReplaySince: EventReplayEvent[];
2663
3017
  getGame: Game;
@@ -2687,8 +3041,9 @@ export interface OperationData {
2687
3041
  getLargeTrade: LargeTradeDetail;
2688
3042
  getMarketCandles: MarketCandles;
2689
3043
  getMarketContextMarkdown: string;
3044
+ getMarketFlow: MarketFlow;
2690
3045
  getMarketHolders: MarketHolder[];
2691
- getMarketIntel: MarketIntel;
3046
+ getMarketIntel: MarketFlow;
2692
3047
  getMarketSnapshot: MarketSnapshot;
2693
3048
  getMonthlyReportSnapshot: ReportSnapshot;
2694
3049
  getPickOfTheDay: PickOfTheDay;
@@ -2707,18 +3062,18 @@ export interface OperationData {
2707
3062
  getTraderExportSnapshot: TraderExportSnapshot;
2708
3063
  getTraderExportStatus: {
2709
3064
  job_id: number;
2710
- /** 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. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed and expired rows stay readable for 48 hours, then the job answers 404. */
2711
- status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired";
3065
+ /** 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. */
3066
+ status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
2712
3067
  format: "json" | "ndjson" | "csv";
2713
3068
  total_trades: number | null;
2714
3069
  processed_trades: number | null;
2715
3070
  file_size: number | null;
2716
3071
  error: string | null;
2717
- /** True when status never changes again (ready, failed, expired). Stop polling. */
3072
+ /** True when status never changes again (ready, failed, expired, cancelled). Stop polling. */
2718
3073
  terminal: boolean;
2719
3074
  /** What to do next: poll the status route after poll_after_s, follow the download route, or submit a new export. Published beside status so a status value added later does not strand a client. */
2720
3075
  next_action: "poll" | "download" | "resubmit";
2721
- /** Seconds to wait before polling again. Absent when terminal. 5 while queued or running; 300 while reconcile_required, the cadence that state can change at. */
3076
+ /** Seconds to wait before polling again. Absent when terminal. 5 while queued, running or cancel_requested; 300 while reconcile_required, the cadence that state can change at. */
2722
3077
  poll_after_s?: number;
2723
3078
  created_at: string;
2724
3079
  /** When the worker last claimed the job; null while queued. */
@@ -2732,20 +3087,29 @@ export interface OperationData {
2732
3087
  expired_at: string | null;
2733
3088
  /** What the file is a snapshot of: the trader's served-data clock (the latest position refresh, else the last completed sync) when the file was written; the same value as export_metadata.data_as_of inside the file. null until the file is written, or when the trader had neither. Read this, not ready_at, to decide whether a reused job is fresh enough; submit with fresh=true for a newer snapshot. */
2734
3089
  data_as_of: string | null;
3090
+ /** When the owner asked to cancel the job; null otherwise. Set on every cancelled job, including one cancelled while queued. While status is cancel_requested this is the instant the worker was asked to stop. */
3091
+ cancel_requested_at: string | null;
3092
+ /** When the job reached cancelled; null until then. */
3093
+ cancelled_at: string | null;
2735
3094
  /** Worker claims so far. */
2736
3095
  attempt: number;
2737
3096
  /** The job fails when attempt reaches this. */
2738
3097
  max_attempts: number;
2739
3098
  /** Present only while status is ready: the stored object's identity, so a client can check the download it receives. */
2740
3099
  artifact?: {
3100
+ /** Stable identity for this completed export artifact; unchanged when a temporary download URL is renewed. */
3101
+ artifact_id: string;
2741
3102
  /** The storage ETag of the object. */
2742
3103
  etag: string | null;
2743
3104
  /** Bytes on the wire (gzip); file_size is the decompressed size. */
2744
3105
  compressed_size_bytes: number | null;
2745
3106
  content_type: "application/json" | "application/x-ndjson" | "text/csv";
2746
3107
  content_encoding: "gzip";
3108
+ /** Immutable manifest for artifacts generated with manifest support; null on historical artifacts written before this contract. */
3109
+ manifest: TraderExportArtifactManifest | null;
2747
3110
  };
2748
3111
  };
3112
+ getTraderGradeAt: TraderGradeAt;
2749
3113
  getTraderPnl: TraderPnl;
2750
3114
  getUsage: {
2751
3115
  rate_limit: {
@@ -2818,18 +3182,18 @@ export interface OperationData {
2818
3182
  searchMarkets: MarketSearchResult[];
2819
3183
  submitTraderExport: {
2820
3184
  job_id: number;
2821
- /** 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. A job that has not reached ready by expires_at reads failed with error 'export expired before completion'. failed and expired rows stay readable for 48 hours, then the job answers 404. */
2822
- status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired";
3185
+ /** 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. */
3186
+ status: "queued" | "running" | "ready" | "failed" | "reconcile_required" | "expired" | "cancel_requested" | "cancelled";
2823
3187
  format: "json" | "ndjson" | "csv";
2824
3188
  total_trades: number | null;
2825
3189
  processed_trades: number | null;
2826
3190
  file_size: number | null;
2827
3191
  error: string | null;
2828
- /** True when status never changes again (ready, failed, expired). Stop polling. */
3192
+ /** True when status never changes again (ready, failed, expired, cancelled). Stop polling. */
2829
3193
  terminal: boolean;
2830
3194
  /** What to do next: poll the status route after poll_after_s, follow the download route, or submit a new export. Published beside status so a status value added later does not strand a client. */
2831
3195
  next_action: "poll" | "download" | "resubmit";
2832
- /** Seconds to wait before polling again. Absent when terminal. 5 while queued or running; 300 while reconcile_required, the cadence that state can change at. */
3196
+ /** Seconds to wait before polling again. Absent when terminal. 5 while queued, running or cancel_requested; 300 while reconcile_required, the cadence that state can change at. */
2833
3197
  poll_after_s?: number;
2834
3198
  created_at: string;
2835
3199
  /** When the worker last claimed the job; null while queued. */
@@ -2843,18 +3207,26 @@ export interface OperationData {
2843
3207
  expired_at: string | null;
2844
3208
  /** What the file is a snapshot of: the trader's served-data clock (the latest position refresh, else the last completed sync) when the file was written; the same value as export_metadata.data_as_of inside the file. null until the file is written, or when the trader had neither. Read this, not ready_at, to decide whether a reused job is fresh enough; submit with fresh=true for a newer snapshot. */
2845
3209
  data_as_of: string | null;
3210
+ /** When the owner asked to cancel the job; null otherwise. Set on every cancelled job, including one cancelled while queued. While status is cancel_requested this is the instant the worker was asked to stop. */
3211
+ cancel_requested_at: string | null;
3212
+ /** When the job reached cancelled; null until then. */
3213
+ cancelled_at: string | null;
2846
3214
  /** Worker claims so far. */
2847
3215
  attempt: number;
2848
3216
  /** The job fails when attempt reaches this. */
2849
3217
  max_attempts: number;
2850
3218
  /** Present only while status is ready: the stored object's identity, so a client can check the download it receives. */
2851
3219
  artifact?: {
3220
+ /** Stable identity for this completed export artifact; unchanged when a temporary download URL is renewed. */
3221
+ artifact_id: string;
2852
3222
  /** The storage ETag of the object. */
2853
3223
  etag: string | null;
2854
3224
  /** Bytes on the wire (gzip); file_size is the decompressed size. */
2855
3225
  compressed_size_bytes: number | null;
2856
3226
  content_type: "application/json" | "application/x-ndjson" | "text/csv";
2857
3227
  content_encoding: "gzip";
3228
+ /** Immutable manifest for artifacts generated with manifest support; null on historical artifacts written before this contract. */
3229
+ manifest: TraderExportArtifactManifest | null;
2858
3230
  };
2859
3231
  };
2860
3232
  updateWebhook: WebhookEndpoint;
@@ -2863,8 +3235,13 @@ export interface OperationData {
2863
3235
  /** Each operation's documented query parameters. */
2864
3236
  export interface OperationQuery {
2865
3237
  activateWebhookSecret: Record<string, never>;
3238
+ batchGetMarketFlow: Record<string, never>;
2866
3239
  batchGetMarketIntel: Record<string, never>;
2867
3240
  batchGetTraders: Record<string, never>;
3241
+ cancelTraderExport: {
3242
+ /** Export job id returned by the submit route. */
3243
+ job_id: number;
3244
+ };
2868
3245
  createMcpJsonRpcResponse: Record<string, never>;
2869
3246
  createWebhook: Record<string, never>;
2870
3247
  deleteWebhook: Record<string, never>;
@@ -2886,6 +3263,7 @@ export interface OperationQuery {
2886
3263
  };
2887
3264
  getAccountIdentity: Record<string, never>;
2888
3265
  getApiDiscovery: Record<string, never>;
3266
+ getCoverage: Record<string, never>;
2889
3267
  getDailyReportSnapshot: {
2890
3268
  /** UTC report date in YYYY-MM-DD format. */
2891
3269
  date: string;
@@ -2919,6 +3297,10 @@ export interface OperationQuery {
2919
3297
  to?: number;
2920
3298
  };
2921
3299
  getMarketContextMarkdown: Record<string, never>;
3300
+ getMarketFlow: {
3301
+ /** Lookback window for whale flow aggregation. */
3302
+ timeframe?: "1h" | "4h" | "24h" | "7d";
3303
+ };
2922
3304
  getMarketHolders: {
2923
3305
  /** Keep holders netting one side. `all` (default) lists both. */
2924
3306
  outcome?: "yes" | "no" | "all";
@@ -2978,8 +3360,12 @@ export interface OperationQuery {
2978
3360
  event?: string;
2979
3361
  /** Optional per-connection subscribe-time filter. Raw provider condition_id or mkt_-prefixed market id (normalized the same way the other v1 market endpoints normalize). A frame passes only when it carries a matching condition_id field; frames that carry no condition_id (e.g. whale-pulse events) are EXCLUDED while this is set. An empty value after normalization returns HTTP 400. Combines with event and min_grade as a logical AND; an absent param adds no constraint. */
2980
3362
  condition_id?: string;
2981
- /** Optional per-connection subscribe-time filter. A frame passes only when it carries a grade field whose grade is better-or-equal to this minimum (S is best). Frames that carry no grade field (every frame except wallet_grade_changed) are EXCLUDED while this is set. An invalid grade returns HTTP 400. Combines with event and condition_id as a logical AND; an absent param adds no constraint. */
3363
+ /** Optional per-connection subscribe-time filter. A frame passes only when it carries a grade field whose grade is better-or-equal to this minimum (S is best). Frames without a grade (every frame except wallet_grade_changed and LargeTradeInsertedV2) are excluded. An invalid grade returns HTTP 400. Combines with the other filters as a logical AND. */
2982
3364
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
3365
+ /** Filter LargeTradeInsertedV2 frames to this Polymarket wallet. Other event types have no wallet and are excluded when set. Applied to live and retained Redis frames after privacy checks. */
3366
+ wallet?: string;
3367
+ /** Filter LargeTradeInsertedV2 frames to trades at or above this USD notional. Positive decimal with at most six places; other event types are excluded when set. */
3368
+ min_size?: string;
2983
3369
  };
2984
3370
  getSuspiciousTrade: Record<string, never>;
2985
3371
  getTrader: {
@@ -2987,6 +3373,8 @@ export interface OperationQuery {
2987
3373
  "expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
2988
3374
  /** Include heavy fields and trust metadata. Repeatable: strategy, categories, quant_metrics, trust. */
2989
3375
  expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
3376
+ /** 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. */
3377
+ max_age_s?: number;
2990
3378
  };
2991
3379
  getTraderCategoryRecords: {
2992
3380
  /** Filter to one canonical category, matched through the same rollup every other category surface uses: soccer, EPL and champions league all reach Soccer, every esports label folds into Esports, and football is AMERICAN football and reaches Football. A filter that reaches Esports returns the Esports record with all of its games; a game is not a filter of its own, so ask for esports and read games. A value that matches no record answers 200 with an empty records array, never 404. */
@@ -2999,6 +3387,10 @@ export interface OperationQuery {
2999
3387
  /** Export job id returned by the submit route. */
3000
3388
  job_id: number;
3001
3389
  };
3390
+ getTraderGradeAt: {
3391
+ /** RFC3339 instant whose historically visible grade is requested. Future instants are refused. Send the trade or decision time, not the ranking date. */
3392
+ as_of: string;
3393
+ };
3002
3394
  getTraderPnl: {
3003
3395
  /** Inclusive UTC calendar-date lower bound in YYYY-MM-DD form for the daily series (entries and drawdown). Omit for the whole stored history. A value that is not a calendar date, or a from later than to, returns 400 bad_request with error.param from. Does not change stats, monthly or year_totals, which stay defined over the full history. */
3004
3396
  from?: string;
@@ -3083,7 +3475,7 @@ export interface OperationQuery {
3083
3475
  limit?: number;
3084
3476
  /** Pagination cursor from previous response's next_cursor. Prefix: wth_. URL-encode when replaying as a query parameter. */
3085
3477
  cursor?: string;
3086
- /** Minimum trade size in USD. The capture floor was 3,000 USD before 2026-07-06 and 10,000 USD from then (1,000 USD in earnings markets), so 10000 gives one size rule across the whole archive. */
3478
+ /** Minimum trade size in USD. The capture floor was 3,000 USD before 2026-07-06 and 10,000 USD from then (1,000 USD in earnings markets), so 10000 gives one size rule across the whole archive. From 2026-09-23 a fill must also be at least 0.1% of its market's recorded traded volume (Polymarket's own share count); rows written before that date were not re-filtered. */
3087
3479
  min_size?: number;
3088
3480
  /** Exact raw provider condition_id. Unknown markets return an empty list. */
3089
3481
  condition_id?: string;
@@ -3101,6 +3493,10 @@ export interface OperationQuery {
3101
3493
  from?: string;
3102
3494
  /** Exclusive RFC3339 upper bound on whale_alerts.traded_at. Must be after from when both are present. */
3103
3495
  to?: string;
3496
+ /** Keep only trades whose market_volume_share is known and at least this. A fraction, not a percent: 0.01 is one percent of the market's traded volume. A trade whose share is unavailable is never returned by a non-zero value, because an unavailable share cannot be said to clear a floor. */
3497
+ min_market_volume_share?: number;
3498
+ /** 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. */
3499
+ sort?: "recent" | "market_volume_share";
3104
3500
  };
3105
3501
  listLargeTrades: {
3106
3502
  /** Maximum number of recent large trades to return. */
@@ -3115,6 +3511,10 @@ export interface OperationQuery {
3115
3511
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
3116
3512
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
3117
3513
  suspicious_only?: boolean;
3514
+ /** Keep only trades whose market_volume_share is known and at least this. A fraction, not a percent: 0.01 is one percent of the market's traded volume. A trade whose share is unavailable is never returned by a non-zero value, because an unavailable share cannot be said to clear a floor. */
3515
+ min_market_volume_share?: number;
3516
+ /** 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 the last 30 days, because the share is computed for each request and an unbounded ranking cannot be served inside the documented latency budget. A cursor is bound to the order it was minted in, so a continuation cannot cross from one order into the other. */
3517
+ sort?: "recent" | "market_volume_share";
3118
3518
  };
3119
3519
  listLeaderboard: {
3120
3520
  /** Maximum number of ranked traders to return. */
@@ -3131,6 +3531,8 @@ export interface OperationQuery {
3131
3531
  limit?: number;
3132
3532
  /** Pagination cursor from previous response's next_cursor. */
3133
3533
  cursor?: string;
3534
+ /** live (default) reads the current value-ordered board. snapshot requires wallet and freezes up to 500 matching rows and 2 MB for up to five minutes. Keep consistency=snapshot and the same effective filters on every page; changing filters returns 400. A new first page from the same API key replaces its prior snapshot; replacement or expiry returns cursor_expired. */
3535
+ consistency?: "live" | "snapshot";
3134
3536
  /** Minimum current position value in USD. Defaults to 100 when omitted, or to 0 when wallet is present; send 0 to include every reconciled position. */
3135
3537
  min_size?: number;
3136
3538
  /** Exact match against provider-backed market_canonical.category. */
@@ -3289,6 +3691,10 @@ export interface OperationQuery {
3289
3691
  from?: string;
3290
3692
  /** Exclusive RFC3339 upper bound on whale_alerts.traded_at. Must be after from when both are present. */
3291
3693
  to?: string;
3694
+ /** Keep only trades whose market_volume_share is known and at least this. A fraction, not a percent: 0.01 is one percent of the market's traded volume. A trade whose share is unavailable is never returned by a non-zero value, because an unavailable share cannot be said to clear a floor. */
3695
+ min_market_volume_share?: number;
3696
+ /** 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. */
3697
+ sort?: "recent" | "market_volume_share";
3292
3698
  };
3293
3699
  listWhaleTrades: {
3294
3700
  /** Maximum number of recent large trades to return. */
@@ -3303,6 +3709,10 @@ export interface OperationQuery {
3303
3709
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
3304
3710
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
3305
3711
  suspicious_only?: boolean;
3712
+ /** Keep only trades whose market_volume_share is known and at least this. A fraction, not a percent: 0.01 is one percent of the market's traded volume. A trade whose share is unavailable is never returned by a non-zero value, because an unavailable share cannot be said to clear a floor. */
3713
+ min_market_volume_share?: number;
3714
+ /** 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 the last 30 days, because the share is computed for each request and an unbounded ranking cannot be served inside the documented latency budget. A cursor is bound to the order it was minted in, so a continuation cannot cross from one order into the other. */
3715
+ sort?: "recent" | "market_volume_share";
3306
3716
  };
3307
3717
  prepareWebhookSecret: Record<string, never>;
3308
3718
  redeliverWebhookDelivery: Record<string, never>;
@@ -3342,8 +3752,13 @@ export interface OperationPath {
3342
3752
  /** Webhook endpoint id owned by the authenticated API key user. */
3343
3753
  id: number;
3344
3754
  };
3755
+ batchGetMarketFlow: Record<string, never>;
3345
3756
  batchGetMarketIntel: Record<string, never>;
3346
3757
  batchGetTraders: Record<string, never>;
3758
+ cancelTraderExport: {
3759
+ /** Trader wallet address (0x...), known trader username-style lookup, or trd_-prefixed trader ID emitted by this API. */
3760
+ address: string;
3761
+ };
3347
3762
  createMcpJsonRpcResponse: Record<string, never>;
3348
3763
  createWebhook: Record<string, never>;
3349
3764
  deleteWebhook: {
@@ -3353,6 +3768,7 @@ export interface OperationPath {
3353
3768
  exploreMarkets: Record<string, never>;
3354
3769
  getAccountIdentity: Record<string, never>;
3355
3770
  getApiDiscovery: Record<string, never>;
3771
+ getCoverage: Record<string, never>;
3356
3772
  getDailyReportSnapshot: Record<string, never>;
3357
3773
  getEventReplaySince: Record<string, never>;
3358
3774
  getGame: {
@@ -3376,6 +3792,10 @@ export interface OperationPath {
3376
3792
  /** 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. */
3377
3793
  condition_id: string;
3378
3794
  };
3795
+ getMarketFlow: {
3796
+ /** 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. */
3797
+ condition_id: string;
3798
+ };
3379
3799
  getMarketHolders: {
3380
3800
  /** 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. */
3381
3801
  condition_id: string;
@@ -3431,6 +3851,10 @@ export interface OperationPath {
3431
3851
  /** Trader wallet address (0x...), known trader username-style lookup, or trd_-prefixed trader ID emitted by this API. */
3432
3852
  address: string;
3433
3853
  };
3854
+ getTraderGradeAt: {
3855
+ /** Wallet address (0x...), username, or trd_-prefixed trader id. */
3856
+ address: string;
3857
+ };
3434
3858
  getTraderPnl: {
3435
3859
  /** Wallet address (0x...), username, or trd_-prefixed trader id. */
3436
3860
  address: string;
@@ -3525,6 +3949,12 @@ export interface OperationPath {
3525
3949
  /** Each operation's JSON request body; `never` when it takes none. */
3526
3950
  export interface OperationBody {
3527
3951
  activateWebhookSecret: never;
3952
+ batchGetMarketFlow: {
3953
+ /** Market condition IDs to resolve in input order. */
3954
+ condition_ids: string[];
3955
+ /** Lookback window used for flow and trade-count context. */
3956
+ timeframe?: "1h" | "4h" | "24h" | "7d";
3957
+ };
3528
3958
  batchGetMarketIntel: {
3529
3959
  /** Market condition IDs to resolve in input order. */
3530
3960
  condition_ids: string[];
@@ -3537,6 +3967,7 @@ export interface OperationBody {
3537
3967
  /** Shared expand flags applied to every trader item. */
3538
3968
  expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
3539
3969
  };
3970
+ cancelTraderExport: never;
3540
3971
  createMcpJsonRpcResponse: {
3541
3972
  /** JSON-RPC protocol version; this server accepts 2.0. */
3542
3973
  jsonrpc: "2.0";
@@ -3552,6 +3983,7 @@ export interface OperationBody {
3552
3983
  exploreMarkets: never;
3553
3984
  getAccountIdentity: never;
3554
3985
  getApiDiscovery: never;
3986
+ getCoverage: never;
3555
3987
  getDailyReportSnapshot: never;
3556
3988
  getEventReplaySince: never;
3557
3989
  getGame: never;
@@ -3560,6 +3992,7 @@ export interface OperationBody {
3560
3992
  getLargeTrade: never;
3561
3993
  getMarketCandles: never;
3562
3994
  getMarketContextMarkdown: never;
3995
+ getMarketFlow: never;
3563
3996
  getMarketHolders: never;
3564
3997
  getMarketIntel: never;
3565
3998
  getMarketSnapshot: never;
@@ -3579,6 +4012,7 @@ export interface OperationBody {
3579
4012
  getTraderContextMarkdown: never;
3580
4013
  getTraderExportSnapshot: never;
3581
4014
  getTraderExportStatus: never;
4015
+ getTraderGradeAt: never;
3582
4016
  getTraderPnl: never;
3583
4017
  getUsage: never;
3584
4018
  getWebhook: never;
@@ -3630,6 +4064,11 @@ export interface OperationResponse {
3630
4064
  data: OperationData["activateWebhookSecret"];
3631
4065
  meta: ResponseMeta;
3632
4066
  };
4067
+ batchGetMarketFlow: {
4068
+ object: "market_flow_batch";
4069
+ data: OperationData["batchGetMarketFlow"];
4070
+ meta: BatchResponseMeta;
4071
+ };
3633
4072
  batchGetMarketIntel: {
3634
4073
  object: "market_intel_batch";
3635
4074
  data: OperationData["batchGetMarketIntel"];
@@ -3640,6 +4079,7 @@ export interface OperationResponse {
3640
4079
  data: OperationData["batchGetTraders"];
3641
4080
  meta: BatchResponseMeta;
3642
4081
  };
4082
+ cancelTraderExport: TraderExportJob;
3643
4083
  createMcpJsonRpcResponse: {
3644
4084
  jsonrpc: "2.0";
3645
4085
  id: string | number | null;
@@ -3679,6 +4119,11 @@ export interface OperationResponse {
3679
4119
  data: OperationData["getApiDiscovery"];
3680
4120
  meta: ResponseMeta;
3681
4121
  };
4122
+ getCoverage: {
4123
+ object: "platforms";
4124
+ data: OperationData["getCoverage"];
4125
+ meta: ResponseMeta;
4126
+ };
3682
4127
  getDailyReportSnapshot: {
3683
4128
  object: "report_snapshot";
3684
4129
  data: OperationData["getDailyReportSnapshot"];
@@ -3719,6 +4164,11 @@ export interface OperationResponse {
3719
4164
  meta: ResponseMeta;
3720
4165
  };
3721
4166
  getMarketContextMarkdown: string;
4167
+ getMarketFlow: {
4168
+ object: "market_flow";
4169
+ data: OperationData["getMarketFlow"];
4170
+ meta: ResponseMeta;
4171
+ };
3722
4172
  getMarketHolders: {
3723
4173
  object: "list";
3724
4174
  data: OperationData["getMarketHolders"];
@@ -3818,6 +4268,11 @@ export interface OperationResponse {
3818
4268
  meta: ResponseMeta;
3819
4269
  };
3820
4270
  getTraderExportStatus: TraderExportJob;
4271
+ getTraderGradeAt: {
4272
+ object: "trader_grade_at";
4273
+ data: OperationData["getTraderGradeAt"];
4274
+ meta: ResponseMeta;
4275
+ };
3821
4276
  getTraderPnl: {
3822
4277
  object: "trader_pnl";
3823
4278
  data: OperationData["getTraderPnl"];
@@ -3882,6 +4337,8 @@ export interface OperationResponse {
3882
4337
  listLargeTradeHistory: {
3883
4338
  object: "list";
3884
4339
  data: OperationData["listLargeTradeHistory"];
4340
+ /** Writer-backed age and coverage for this page; it is part of the representation and the ETag, while transport cache facts remain in meta. */
4341
+ data_quality: DataQuality;
3885
4342
  has_more: boolean;
3886
4343
  next_cursor?: string;
3887
4344
  /** Total matching rows when the read model exposes a count; the key is absent when it does not. */
@@ -3891,6 +4348,8 @@ export interface OperationResponse {
3891
4348
  listLargeTrades: {
3892
4349
  object: "list";
3893
4350
  data: OperationData["listLargeTrades"];
4351
+ /** Writer-backed age and coverage for this page; it is part of the representation and the ETag, while transport cache facts remain in meta. */
4352
+ data_quality: DataQuality;
3894
4353
  has_more: boolean;
3895
4354
  next_cursor?: string;
3896
4355
  /** Total matching rows when the read model exposes a count; absent (or null) when it does not. */
@@ -3909,10 +4368,18 @@ export interface OperationResponse {
3909
4368
  listPositions: {
3910
4369
  object: "list";
3911
4370
  data: OperationData["listPositions"];
4371
+ /** Writer-backed age and coverage for this page; it is part of the representation and the ETag, while transport cache facts remain in meta. */
4372
+ data_quality: DataQuality;
3912
4373
  has_more: boolean;
3913
4374
  next_cursor?: string;
3914
4375
  /** Total matching rows when the read model exposes a count; the key is absent when it does not. */
3915
4376
  total?: number;
4377
+ /** Present only with consistency=snapshot. Dates the frozen response rows, not the provider's underlying observations. */
4378
+ snapshot?: {
4379
+ as_of: string;
4380
+ expires_at: string;
4381
+ row_count: number;
4382
+ };
3916
4383
  meta: ResponseMeta;
3917
4384
  };
3918
4385
  listPreGameSideObservations: {
@@ -4027,6 +4494,8 @@ export interface OperationResponse {
4027
4494
  listWhaleTradeHistory: {
4028
4495
  object: "list";
4029
4496
  data: OperationData["listWhaleTradeHistory"];
4497
+ /** Writer-backed age and coverage for this page; it is part of the representation and the ETag, while transport cache facts remain in meta. */
4498
+ data_quality: DataQuality;
4030
4499
  has_more: boolean;
4031
4500
  next_cursor?: string;
4032
4501
  /** Total matching rows when the read model exposes a count; absent (or null) when it does not. */
@@ -4036,6 +4505,8 @@ export interface OperationResponse {
4036
4505
  listWhaleTrades: {
4037
4506
  object: "list";
4038
4507
  data: OperationData["listWhaleTrades"];
4508
+ /** Writer-backed age and coverage for this page; it is part of the representation and the ETag, while transport cache facts remain in meta. */
4509
+ data_quality: DataQuality;
4039
4510
  has_more: boolean;
4040
4511
  next_cursor?: string;
4041
4512
  /** Total matching rows when the read model exposes a count; the key is absent when it does not. */