@0xinsider/mcp 3.11.0 → 3.13.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 (54) hide show
  1. package/README.md +3 -3
  2. package/dist/constants.d.ts +1 -1
  3. package/dist/constants.js +1 -1
  4. package/dist/product-cli/client.js +1 -1
  5. package/dist/product-cli/index.d.ts.map +1 -1
  6. package/dist/product-cli/index.js +1 -0
  7. package/dist/product-cli/index.js.map +1 -1
  8. package/dist/product-cli/operations.d.ts +2 -1
  9. package/dist/product-cli/operations.d.ts.map +1 -1
  10. package/dist/product-cli/operations.js +9 -6
  11. package/dist/product-cli/operations.js.map +1 -1
  12. package/dist/sdk/client.d.ts +5 -3
  13. package/dist/sdk/client.d.ts.map +1 -1
  14. package/dist/sdk/client.js.map +1 -1
  15. package/dist/sdk/index.d.ts +1 -1
  16. package/dist/sdk/index.d.ts.map +1 -1
  17. package/dist/sdk/index.js.map +1 -1
  18. package/dist/sdk/schema.d.ts +1072 -170
  19. package/dist/sdk/schema.d.ts.map +1 -1
  20. package/dist/sdk/stream.d.ts +35 -2
  21. package/dist/sdk/stream.d.ts.map +1 -1
  22. package/dist/sdk/stream.js +14 -1
  23. package/dist/sdk/stream.js.map +1 -1
  24. package/dist/tools/explore-markets.js +2 -2
  25. package/dist/tools/explore-markets.js.map +1 -1
  26. package/dist/tools/games.js +2 -2
  27. package/dist/tools/games.js.map +1 -1
  28. package/dist/tools/get-large-positions.js +2 -2
  29. package/dist/tools/get-large-positions.js.map +1 -1
  30. package/dist/tools/get-leaderboard.js +3 -3
  31. package/dist/tools/get-leaderboard.js.map +1 -1
  32. package/dist/tools/get-positions.js +2 -2
  33. package/dist/tools/get-positions.js.map +1 -1
  34. package/dist/tools/get-trader.d.ts.map +1 -1
  35. package/dist/tools/get-trader.js +5 -4
  36. package/dist/tools/get-trader.js.map +1 -1
  37. package/dist/tools/get-whale-trades.d.ts.map +1 -1
  38. package/dist/tools/get-whale-trades.js +12 -7
  39. package/dist/tools/get-whale-trades.js.map +1 -1
  40. package/dist/tools/pick-of-the-day.d.ts.map +1 -1
  41. package/dist/tools/pick-of-the-day.js +82 -16
  42. package/dist/tools/pick-of-the-day.js.map +1 -1
  43. package/dist/tools/read-parity.d.ts.map +1 -1
  44. package/dist/tools/read-parity.js +28 -20
  45. package/dist/tools/read-parity.js.map +1 -1
  46. package/dist/tools/result.d.ts +6 -0
  47. package/dist/tools/result.d.ts.map +1 -1
  48. package/dist/tools/result.js +2 -0
  49. package/dist/tools/result.js.map +1 -1
  50. package/dist/tools/search-markets.js +2 -2
  51. package/dist/tools/search-markets.js.map +1 -1
  52. package/dist/tools/trader-reads.js +2 -2
  53. package/dist/tools/trader-reads.js.map +1 -1
  54. package/package.json +1 -1
@@ -51,6 +51,23 @@ export type AgentRegistration = {
51
51
  auth_guide_url: string;
52
52
  };
53
53
  };
54
+ /** A computed count with its truth state; the same envelope as AnalyticNumber. */
55
+ export type AnalyticInteger = {
56
+ state: "computed" | "known_zero" | "not_computed" | "not_applicable" | "stale" | "unavailable" | "insufficient_data";
57
+ source: "provider" | "insert_time" | "cache" | "computed";
58
+ value?: number;
59
+ freshness_at?: string;
60
+ };
61
+ /** A computed number with its truth state. value is present when state is computed or known_zero and may be present when stale; any other state says why there is no number, never a stand-in zero. */
62
+ export type AnalyticNumber = {
63
+ /** computed: a measured value. known_zero: a measured zero. stale: a value past its freshness window. not_computed: an input is unknown. not_applicable: the measure does not apply. unavailable: the source could not be read. insufficient_data: too few observations. */
64
+ state: "computed" | "known_zero" | "not_computed" | "not_applicable" | "stale" | "unavailable" | "insufficient_data";
65
+ /** Where the value came from, for diagnostics: cache is a stored aggregate, computed a request-time aggregate. Decide on state, not source. */
66
+ source: "provider" | "insert_time" | "cache" | "computed";
67
+ value?: number;
68
+ /** When the stored inputs behind the value were written or last confirmed (cache), or the request time (computed). */
69
+ freshness_at?: string;
70
+ };
54
71
  export type ApiDiscovery = {
55
72
  /** Canonical API origin for public V1 requests. */
56
73
  api_base_url: string;
@@ -984,6 +1001,7 @@ export type EventReplayMeta = {
984
1001
  condition_id?: string;
985
1002
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
986
1003
  min_size?: number;
1004
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
987
1005
  };
988
1006
  /** The expansions applied to every event on this page; empty when none. */
989
1007
  expand: "trade"[];
@@ -1330,10 +1348,12 @@ export type GameHoldersItem = {
1330
1348
  market: MarketHoldersMarket;
1331
1349
  scan: MarketHoldersScan;
1332
1350
  totals: MarketHoldersTotals;
1333
- /** When this roster was computed. A cached roster is at most 60 seconds old. */
1351
+ /** When this roster was computed. A fresh cached roster is at most 60 seconds old; a stale one at most 15 minutes. */
1334
1352
  computed_at: string;
1335
- /** true when the roster came from the 60-second roster cache. */
1353
+ /** true when the roster came from the cache. */
1336
1354
  cached: boolean;
1355
+ /** true when the market had no fresh roster at the batch deadline and this is the last roster published for it, up to 15 minutes old (read computed_at). The fresh one is still computing, so a read a few seconds later normally gets it; a market refused over the account's cold-read share is served the same way. */
1356
+ stale: boolean;
1337
1357
  };
1338
1358
  /** One Polymarket market linked to this game. */
1339
1359
  export type GameMarket = {
@@ -1793,7 +1813,7 @@ export type LargeTradeInsertedV2Data = {
1793
1813
  trader_id: number;
1794
1814
  /** Address of the wallet that made the trade. */
1795
1815
  wallet: string;
1796
- /** The wallet's grade when the event was published; `null` when it has none. */
1816
+ /** The wallet's grade when the event was published; `null` when it has none. A backfilled trade publishes hours after it filled, so this can differ from `grade_at_trade`. `min_grade` filters on this field; `min_grade_at_trade` filters on `grade_at_trade`. */
1797
1817
  grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
1798
1818
  /** USD notional of the trade; decimal string. */
1799
1819
  size_usd: string;
@@ -1807,20 +1827,26 @@ export type LargeTradeInsertedV2Data = {
1807
1827
  /** When the trade filled on Polymarket. The envelope's `created_at` is this instant. */
1808
1828
  traded_at: string;
1809
1829
  platform: "polymarket";
1830
+ /** The grade the wallet held when the trade filled, the same fact as `trader.grade_at_trade` on `GET /api/v1/large-trades`; `null` unless `grade_at_trade_status` is `graded`. `min_grade_at_trade` filters on it. */
1831
+ grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F" | null;
1832
+ /** `graded` when `grade_at_trade` holds the grade at the fill; `ungraded` when the wallet had no grade then; `unknown` when it cannot be known, for a trade before 2026-09-19 23:00 UTC or while a grade change is unconfirmed. Only `graded` trades match `min_grade_at_trade`. An event published before these fields shipped (November 2026), or a redelivery of one, carries neither. */
1833
+ grade_at_trade_status?: "graded" | "ungraded" | "unknown";
1810
1834
  };
1811
1835
  /** `large_trades_inserted` data (Pro and Max): new large trades were ingested. It carries a count and no trade; subscribe to `large_trade_inserted_v2` for the trade itself. The deprecated spelling `whale_trades_inserted` delivers the same object until its sunset on 2027-02-01 (#29352). */
1812
1836
  export type LargeTradesInsertedData = {
1813
1837
  /** Large trades the producing batch admitted. */
1814
1838
  count: number;
1815
1839
  };
1816
- /** 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. */
1840
+ /** All present fields narrow large_trade_inserted_v2 delivery. min_grade reads the payload's grade, observed at publication; min_grade_at_trade reads its grade_at_trade, the grade when the trade filled. Send one of the two, not both (400). An empty object matches every large trade. */
1817
1841
  export type LargeTradeSubscriptionFilters = {
1818
1842
  /** Raw provider condition ID or mkt_-prefixed market ID. */
1819
1843
  condition_id?: string;
1820
1844
  /** Polymarket wallet address; matching is case-insensitive. */
1821
1845
  wallet?: string;
1822
- /** S is best; ungraded trades do not match. */
1846
+ /** S is best; ungraded trades do not match. Reads the wallet's grade when the trade was published, which for a backfilled trade can be hours after the fill. */
1823
1847
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
1848
+ /** S is best. Reads grade_at_trade, the grade the trader held when the trade filled; only a trade whose grade_at_trade_status is graded matches. The same basis as min_grade_at_trade on GET /api/v1/large-trades and GET /api/v1/stream. */
1849
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
1824
1850
  /** Positive USD notional as an exact decimal string. */
1825
1851
  min_size_usd?: string;
1826
1852
  };
@@ -1867,17 +1893,28 @@ export type LeaderboardEntry = {
1867
1893
  /** When the wallet last traded: its most recent recorded trade, as of the leaderboard row's last refresh, which re-reads it hourly, so a new trade can take about an hour to show. It agrees with the activity filter: every wallet listed under activity=inactive last traded more than 30 days ago. Since 2026-11-02 (#32322); before, it carried the time 0xinsider last synced the wallet, usually within the past week whether or not the wallet traded. Omitted when the wallet has no recorded trade. */
1868
1894
  last_active?: string;
1869
1895
  };
1896
+ /** Every league with a skill leaderboard, by sport: the league values GET /api/v1/leaderboard/sports/{sport} accepts. */
1870
1897
  export type LeaderboardLeagues = {
1898
+ /** Grouped by sport, then most ranked wallets first. */
1871
1899
  leagues: {
1900
+ /** The canonical sport, for example Soccer or Esports. */
1872
1901
  category: string;
1902
+ /** The league's display name. */
1873
1903
  name: string;
1904
+ /** Wallets the league board's edge sort ranks with no hold; at least min_ranked. */
1874
1905
  ranked_traders: number;
1906
+ /** The league slug, the board route's league parameter. */
1875
1907
  slug: string;
1908
+ /** The sport slug, the board route's {sport}. */
1876
1909
  sport: string;
1910
+ /** Wallets with at least min_resolved settled markets in the league and a trade in the last 180 days: the field the league board ranks. */
1877
1911
  total_traders: number;
1878
1912
  }[];
1913
+ /** Wallets a league board's edge sort must rank, with no hold, for the league to be listed. */
1879
1914
  min_ranked: number;
1915
+ /** Settled markets of $20 or more a wallet needs in a league to be on its board. */
1880
1916
  min_resolved: number;
1917
+ /** When the league ranking last ran. It runs about once a day. */
1881
1918
  refreshed_at: string;
1882
1919
  };
1883
1920
  /** Edge over the price paid (#32270): how often the side a wallet bought won, minus the average price it paid, over its settled sports and esports markets of $20 or more at a known entry price. Probabilities throughout: edge 0.12 is 12 percentage points. A wallet buying at 99 cents that wins every market has an edge of about 0.01. A market bought on both sides counts by its shares: the winning side's share of the shares bought is its hit, the cost over those shares its price. */
@@ -1895,6 +1932,21 @@ export type LeaderboardPriceEdge = {
1895
1932
  /** Why the leaderboard does not rank a ranked edge. record_incomplete: the wallet's stored sports and esports record shows more profit than Polymarket reports for it, so some losing markets are likely missing. Omitted when nothing holds the edge, and always omitted unless status is ranked. */
1896
1933
  hold?: "record_incomplete";
1897
1934
  };
1935
+ /** The whole board's totals, the counts the 0xinsider leaderboard page shows (#32737), read with the ranking snapshot the page is served at. Sent on every page of a request with no category and no strategy, whatever its sort, dir and activity, which order or split the same wallets. Omitted on a category or strategy page, which lists a subset these totals do not describe, and while the ranking has no totals for the served generation. */
1936
+ export type LeaderboardSummary = {
1937
+ /** Ranked wallets on the board: the wallets the unfiltered list pages through. */
1938
+ ranked_total: number;
1939
+ /** Ranked wallets by grade. Every ranked wallet is graded S, A or B, so the three sum to ranked_total. */
1940
+ by_grade: {
1941
+ S: number;
1942
+ A: number;
1943
+ B: number;
1944
+ };
1945
+ /** Ranked wallets whose last trade was 30 days or less before as_of: the wallets activity=active lists. ranked_total minus active_30d is the activity=inactive count. */
1946
+ active_30d: number;
1947
+ /** When the totals were counted, UTC. They are recounted about once a minute while the ranking is current. */
1948
+ as_of: string;
1949
+ };
1898
1950
  /** One side's score line inside a `live_sports_updated` pulse. */
1899
1951
  export type LiveSportsScoreEntry = {
1900
1952
  /** Team name, ordered for the league (away first where the league reads that way). */
@@ -2630,6 +2682,13 @@ export type PickOfTheDayArchive = {
2630
2682
  /** One entry per product day that has a published pick included in the archive, newest first, in the same order as picks. Each carries that day's net units, accumulated in the same backend pass and behind the same visibility gate as hit_rate.unit_score, so both cover the same population of picks. Re-adding the day totals reproduces hit_rate.unit_score to display precision rather than bit-for-bit, since that re-associates the floating-point sum. */
2631
2683
  days: PickOfTheDayArchiveDay[];
2632
2684
  hit_rate: PickOfTheDayHitRate;
2685
+ page?: {
2686
+ has_more: boolean;
2687
+ limit: number;
2688
+ next_cursor: string | null;
2689
+ returned: number;
2690
+ total: number;
2691
+ };
2633
2692
  };
2634
2693
  export type PickOfTheDayArchiveDay = {
2635
2694
  /** The product day (YYYY-MM-DD). */
@@ -2725,6 +2784,67 @@ export type PickOfTheDayArchiveEntry = {
2725
2784
  */
2726
2785
  supersedes_pick_id: string | null;
2727
2786
  };
2787
+ /** The archive with `view=summary`: `hit_rate` without its daily `series`, one short row per pick, and `page`. Page with `limit` and `cursor`; `view=full` returns every field of a row. */
2788
+ export type PickOfTheDayArchiveSummary = {
2789
+ hit_rate: {
2790
+ clv_applicable: number;
2791
+ clv_avg_display?: string;
2792
+ clv_avg_pct?: number;
2793
+ clv_avg_pp?: number;
2794
+ clv_avg_pp_display?: string;
2795
+ clv_beats_close: number;
2796
+ clv_coverage_display?: string;
2797
+ clv_coverage_explanation?: string;
2798
+ clv_coverage_pct?: number;
2799
+ clv_eligible: number;
2800
+ clv_measured: number;
2801
+ clv_not_applicable: number;
2802
+ clv_pending: number;
2803
+ clv_state: string;
2804
+ clv_ties: number;
2805
+ clv_total: number;
2806
+ clv_unavailable: number;
2807
+ decided: number;
2808
+ losses: number;
2809
+ net_profit_display: string;
2810
+ net_profit_usd: number;
2811
+ pct: number;
2812
+ pending: number;
2813
+ roi_display: string;
2814
+ roi_pct: number;
2815
+ stake_usd: number;
2816
+ staked_usd: number;
2817
+ unit_score?: number;
2818
+ unit_score_display?: string;
2819
+ void: number;
2820
+ win_rate_display: string;
2821
+ wins: number;
2822
+ };
2823
+ page: {
2824
+ has_more: boolean;
2825
+ limit: number;
2826
+ next_cursor: string | null;
2827
+ returned: number;
2828
+ total: number;
2829
+ };
2830
+ picks: {
2831
+ backed_price?: number;
2832
+ backed_side_locked?: boolean;
2833
+ clv_pct?: number;
2834
+ display_category?: string;
2835
+ is_free_selection: boolean;
2836
+ matchup?: string;
2837
+ outcome: string;
2838
+ pick_date: string;
2839
+ pick_id: string;
2840
+ pick_outcome_label?: string;
2841
+ publication_order: number;
2842
+ required_tier?: string;
2843
+ top_grade?: string;
2844
+ unit_score?: number;
2845
+ }[];
2846
+ view: string;
2847
+ };
2728
2848
  /** Select using the entry commitment_version, never implicit payload shape. All historic v1 hashes remain unchanged. */
2729
2849
  export type PickOfTheDayCommitmentPayload = PickOfTheDayCommitmentPayloadV1 | PickOfTheDayCommitmentPayloadV2;
2730
2850
  /** The frozen identity of the pick, exactly as the hash was taken over it. Served byte for byte as it was hashed -- keys sorted by UTF-8 byte value, no insignificant whitespace -- so a verifier concatenates and hashes with nothing to reconstruct. Property order below is the wire order. The outcome is deliberately NOT part of it: surviving a corrected outcome unchanged is the case the commitment exists for. Worked example: {"backed_price":"0.545000","condition_id":"0xabc","kickoff":"2026-09-20T23:05:00Z","pick_date":"2026-09-20","pick_outcome_index":1,"pick_outcome_label":"Lakers","pick_rank":1,"platform":"polymarket"} with the nonce 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f hashes to 44d18fa5e2aa3a2bf3c971dcc9317c8ccbdfd5480a4773b6d8ffd5fbeeea84dc. */
@@ -2902,6 +3022,8 @@ export type PickOfTheDayLedgerOpenedEntry = {
2902
3022
  supersedes_pick_id: string | null;
2903
3023
  /** Explicit proof provenance: 1 retains historic eight-field canonical JSON; 2 binds stable pick_id and version without pick_rank. */
2904
3024
  commitment_version: 1 | 2;
3025
+ /** How the pick was chosen: auto by the selection algorithm, manual by an operator (102 published picks from 2026-06-23 to 2026-10-15; none since). Outside the hashed payload, so it moves no commitment. */
3026
+ selected_by: "auto" | "manual";
2905
3027
  };
2906
3028
  /** An unresolved published pick. Carries only date, rank, hash, algorithm, seal instant and permalink. Kickoff and game identity are withheld; seal time remains public commitment provenance. */
2907
3029
  export type PickOfTheDayLedgerSealedEntry = {
@@ -2934,6 +3056,8 @@ export type PickOfTheDayLedgerSealedEntry = {
2934
3056
  supersedes_pick_id: string | null;
2935
3057
  /** Explicit proof provenance: 1 retains historic eight-field canonical JSON; 2 binds stable pick_id and version without pick_rank. */
2936
3058
  commitment_version: 1 | 2;
3059
+ /** How the pick was chosen: auto by the selection algorithm, manual by an operator (102 published picks from 2026-06-23 to 2026-10-15; none since). Outside the hashed payload, so it moves no commitment. */
3060
+ selected_by: "auto" | "manual";
2937
3061
  };
2938
3062
  /** A pick without a commitment, retained so the record cannot omit unprovable entries. Unresolved entries omit game identity; once resolved, matchup, category and payload become public. Existing opened canonical payload bytes and hashes are unchanged. */
2939
3063
  export type PickOfTheDayLedgerUncommittedEntry = {
@@ -2972,6 +3096,8 @@ export type PickOfTheDayLedgerUncommittedEntry = {
2972
3096
  * @deprecated
2973
3097
  */
2974
3098
  supersedes_pick_id: string | null;
3099
+ /** How the pick was chosen: auto by the selection algorithm, manual by an operator (102 published picks from 2026-06-23 to 2026-10-15; none since). Outside the hashed payload, so it moves no commitment. */
3100
+ selected_by: "auto" | "manual";
2975
3101
  };
2976
3102
  /** A successful current-day entitlement response when only unauthorized ranks have published. It carries an empty pick set, identity-free locked ranks and an upgrade message. Selection IDs, game identity, prices and unauthorized clocks are absent. Any scheduled or proof-pending rows are entitled rows. */
2977
3103
  export type PickOfTheDayNoEntitledPicks = {
@@ -3396,145 +3522,647 @@ export type PickOfTheDayStats = {
3396
3522
  pick_id: string;
3397
3523
  pick_rank: number;
3398
3524
  }[];
3525
+ selections: {
3526
+ canonical_category?: string;
3527
+ clv_avg_display?: string;
3528
+ clv_avg_pct?: number;
3529
+ clv_avg_pp?: number;
3530
+ clv_avg_pp_display?: string;
3531
+ clv_measured: number;
3532
+ edge_display?: string;
3533
+ edge_pp?: number;
3534
+ key: string;
3535
+ label: string;
3536
+ losses: number;
3537
+ net_profit_display?: string;
3538
+ net_profit_usd?: number;
3539
+ pending: number;
3540
+ picks: number;
3541
+ priced_decided: number;
3542
+ priced_in_display?: string;
3543
+ priced_in_pct?: number;
3544
+ roi_display?: string;
3545
+ roi_pct?: number;
3546
+ settled: number;
3547
+ small_sample: boolean;
3548
+ staked_usd: number;
3549
+ unit_score?: number;
3550
+ unit_score_display?: string;
3551
+ void: number;
3552
+ win_rate_display?: string;
3553
+ win_rate_pct?: number;
3554
+ wins: number;
3555
+ }[];
3399
3556
  };
3400
- /** A settled uncommitted pick's market, side and price. The same eight fields as PickOfTheDayCommitmentPayload, in the same key order, so a settled pick's side and price sit under payload whatever the entry's state. It is NOT a commitment: no hash was taken over it before the game, and it proves nothing about when the pick was made. */
3401
- export type PickOfTheDayUncommittedPayload = {
3402
- /** Frozen pre-game price of the backed side, 0..1, as the plain decimal text of the stored NUMERIC at full stored precision, trailing zeros included -- rendered exactly as the commitment payload renders it. */
3403
- backed_price: string;
3404
- /** Provider condition id of the backed market. */
3405
- condition_id: string;
3406
- /** Frozen provider kickoff, UTC, literal Z; null when no kickoff was frozen. Whole seconds render exactly as the commitment payload does; a sub-second instant keeps its fraction rather than being truncated, since nothing here is hashed. */
3407
- kickoff: string | null;
3408
- /** ET product day (YYYY-MM-DD). */
3409
- pick_date: string;
3410
- /** Index of the backed outcome within the market. */
3411
- pick_outcome_index: 0 | 1;
3412
- /** Frozen display label of the backed outcome. */
3413
- pick_outcome_label: string;
3414
- /** 1-based daily slot. */
3415
- pick_rank: number;
3416
- /** Provider platform. Always polymarket. */
3417
- platform: "polymarket";
3418
- };
3419
- /** Provider-first sports context for a Pick of the Day market: team crests, league branding, and live score. Each team `logo` is a registered club crest or national flag as a same-origin path where one exists, and provider artwork otherwise. */
3420
- export type PickSportsContext = {
3421
- /** League or competition display name (e.g. "Premier League"). */
3422
- league_name: string | null;
3423
- /** Provider-owned event taxonomy from Gamma eventMetadata, joined in league · serie · tournament order with blanks and case-insensitive duplicates removed. A tennis qualifying match ends in ", Qualification", including an ATP Challenger qualifying match, which Gamma marks only in eventMetadata.tennisFixtureSource. Separate from league_name; omitted when the provider does not supply the metadata. */
3424
- competition_label?: string;
3425
- /** League logo URL (provider-owned). */
3426
- league_logo: string | null;
3427
- /** The team mapped to the market's YES outcome, or the parent-event home/first team when event_matchup is true. */
3428
- yes_team: PickSportsTeam | null;
3429
- /** The team mapped to the market's NO outcome, or the parent-event away/second team when event_matchup is true. */
3430
- no_team: PickSportsTeam | null;
3431
- /** Provider game identifier (Polymarket Gamma gameId); omitted when the provider supplies none. */
3432
- game_id?: number;
3433
- /** Always present. True when the two teams are the parent-event match identity for a teamless binary leg (e.g. a draw, totals, or prop market), not the market's own outcomes. */
3434
- event_matchup: boolean;
3435
- /** Present only alongside event_matchup: the event team the binary leg is about (provider group_item_title matched to a matchup team, e.g. Belgium for "Will Belgium win?"), i.e. the winner on a Yes resolution. Omitted for teamless legs (draw, totals, prop). */
3436
- event_subject_team?: PickSportsTeam;
3437
- /** The two teams as a single whole-game label, joined "<home> – <away>" (en-dash) in provider display order (e.g. "Portugal – Uzbekistan"). Composed server-side from the provider team names (no title/slug parsing). Present when both teams resolve a name; omitted for single-subject, teamless, or non-two-team contexts. */
3438
- matchup_title?: string;
3439
- };
3440
- /** A single sports team or competitor in a Pick of the Day market's sports context. Identity and score fields are provider-owned and nullable. The structured score fields (`sets`, `format`, `sets_won`) and the tennis fields (`headshot`, `headshot_revision`, `tour`) are backend-owned and are OMITTED rather than null when they do not apply, so a consumer must treat an absent key and a null the same way. */
3441
- export type PickSportsTeam = {
3442
- /** Team display label as it appears on the market outcome (e.g. "Portugal"). */
3443
- label: string | null;
3444
- /** Abbreviated team label (e.g. "POR"). */
3445
- short_label: string | null;
3446
- /** The name to show for this team or competitor, the same on every surface (e.g. "UCF Knights", "Oklahoma City Thunder", "Portugal"). `label` keeps the market outcome's own spelling. */
3447
- full_name: string | null;
3448
- /** Provider team identifier (Polymarket /teams id). */
3449
- provider_id: number | null;
3450
- /** Team crest or flag URL. Official NFL (32), WNBA (15), NBA (30), NHL (32), and MLB (30) club crests use same-origin relative paths (`/api/sports/team-logos/{league}/{abbr}.svg?v=<content hash>`); resolve relative URLs against the API origin. Vendored soccer club crests use the same path with `.png`. National teams in the registered national-team competitions use the same path with `.svg`: the official national flag, drawn whole at its own aspect. Other teams use provider artwork, including country flags for tennis players. Novelty rows, and national-team rows that are not exactly one country, retain provider artwork. */
3451
- logo: string | null;
3452
- /** True when artwork measurements show that the team mark needs a light plate on a dark background. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured by the teams sync. Always sent; false when no current measurement marks the logo dark. */
3453
- logo_mark_dark: boolean;
3454
- /** Team brand color as a hex string (provider-owned). */
3455
- color: string | null;
3456
- /** Win-loss record as a display string (e.g. "12-4"). */
3457
- record: string | null;
3458
- /** Live or final score as a display string when the game is in play or settled. */
3459
- score: string | null;
3460
- /** Tennis player headshot URL, served same-origin. Present only for a tennis competitor the headshot resolver matched; absent for team sports and for unmatched players, where `logo` stays the fallback. */
3461
- headshot?: string;
3462
- /** Tennis tour this competitor belongs to. Present for every tennis entry whether or not `headshot` resolved, so a consumer can tell a tennis player with no photo from a non-tennis team. Absent for every other sport. Only `atp` and `wta` name a gender; the ITF World Tennis Tour runs men's and women's events and the provider does not say which, so `itf` means tennis with gender unknown. */
3463
- tour?: "atp" | "wta" | "itf";
3464
- /** Per-set score cells for this side, in set order. Backend-owned: render these rather than parsing `score`. Omitted entirely when the provider score is not a structured multi-set match or could not be parsed, so an absent array and an empty one carry the same meaning. */
3465
- sets?: ScoreCell[];
3466
- format?: ScoreFormat;
3467
- /** Completed sets won by this side. Present only when both sides expose the same set columns, so a partially parsed scoreline reports no tally rather than a misleading one. */
3468
- sets_won?: number;
3469
- /** Optional monotonic photo revision for this tennis player, independent of the sports score revision. Legacy stored photos start at zero. Successful new or changed image bytes advance it; source checks and attribution changes do not. Compare only for the same tour and provider_id: a higher revision replaces the portrait, an equal revision may fill a missing portrait, and a lower revision must not replace a newer one. Absent when no photo resolved. */
3470
- headshot_revision?: number;
3471
- /** Optional latest retrieved ATP/WTA singles rank for this player. Absent for unranked, ambiguous, doubles, expired, or unavailable identities. This is not rank at match time. */
3472
- ranking?: TennisRanking;
3473
- /** True when artwork measurements show that the team mark disappears on a white background and needs a dark plate there: the light-background twin of logo_mark_dark. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured on white by the teams sync. Always sent; false when no current measurement marks the logo light. */
3474
- logo_mark_light: boolean;
3475
- /** True when logo_mark_dark and logo_mark_light are both measurements of this exact logo URL, so their false means the mark is legible on that background. Every vendored crest is measured; a provider logo is measured once the teams sync has scored it, usually within a few hourly cycles of first appearing. Always sent; false while the logo is not measured yet. */
3476
- logo_mark_measured: boolean;
3477
- };
3478
- export type PlatformCapabilities = {
3479
- grade: PlatformCapabilityStatus;
3480
- pnl: PlatformCapabilityStatus;
3481
- strategy: PlatformCapabilityStatus;
3482
- timeline: PlatformCapabilityStatus;
3483
- /** The large-trade feed. Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
3484
- large_trades: PlatformCapabilityStatus;
3485
- /**
3486
- * Deprecated spelling of large_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trades.
3487
- * @deprecated
3488
- */
3489
- whale_signal: PlatformCapabilityStatus;
3490
- suspicious_trades: PlatformCapabilityStatus;
3491
- /**
3492
- * Deprecated spelling of suspicious_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read suspicious_trades.
3493
- * @deprecated
3494
- */
3495
- insider_radar: PlatformCapabilityStatus;
3496
- market_snapshot: PlatformCapabilityStatus;
3497
- };
3498
- /** Every capability the API serves reports supported. The field names a per-capability status so a client can branch on coverage; no other value is emitted. */
3499
- export type PlatformCapabilityStatus = "supported";
3500
- export type Platforms = {
3501
- platforms: {
3502
- polymarket: PlatformCapabilities;
3557
+ /** The stats with `view=summary` or `sections`: only the named sections, listed in `sections`. `view=summary` names every section except `series`, `days`, `categories`, `months` and `voids`. */
3558
+ export type PickOfTheDayStatsSections = {
3559
+ categories?: {
3560
+ canonical_category?: string;
3561
+ clv_avg_display?: string;
3562
+ clv_avg_pct?: number;
3563
+ clv_avg_pp?: number;
3564
+ clv_avg_pp_display?: string;
3565
+ clv_measured: number;
3566
+ edge_display?: string;
3567
+ edge_pp?: number;
3568
+ key: string;
3569
+ label: string;
3570
+ losses: number;
3571
+ net_profit_display?: string;
3572
+ net_profit_usd?: number;
3573
+ pending: number;
3574
+ picks: number;
3575
+ priced_decided: number;
3576
+ priced_in_display?: string;
3577
+ priced_in_pct?: number;
3578
+ roi_display?: string;
3579
+ roi_pct?: number;
3580
+ settled: number;
3581
+ small_sample: boolean;
3582
+ staked_usd: number;
3583
+ unit_score?: number;
3584
+ unit_score_display?: string;
3585
+ void: number;
3586
+ win_rate_display?: string;
3587
+ win_rate_pct?: number;
3588
+ wins: number;
3589
+ }[];
3590
+ days?: ({
3591
+ date: string;
3592
+ losses: number;
3593
+ net_profit_display?: string;
3594
+ net_profit_usd?: number;
3595
+ pending: number;
3596
+ picks: number;
3597
+ sweep?: "win" | "loss";
3598
+ unit_score?: number;
3599
+ unit_score_display?: string;
3600
+ void: number;
3601
+ wins: number;
3602
+ })[];
3603
+ hit_rate?: {
3604
+ clv_applicable: number;
3605
+ clv_avg_display?: string;
3606
+ clv_avg_pct?: number;
3607
+ clv_avg_pp?: number;
3608
+ clv_avg_pp_display?: string;
3609
+ clv_beats_close: number;
3610
+ clv_coverage_display?: string;
3611
+ clv_coverage_explanation?: string;
3612
+ clv_coverage_pct?: number;
3613
+ clv_eligible: number;
3614
+ clv_measured: number;
3615
+ clv_not_applicable: number;
3616
+ clv_pending: number;
3617
+ clv_state: string;
3618
+ clv_ties: number;
3619
+ clv_total: number;
3620
+ clv_unavailable: number;
3621
+ decided: number;
3622
+ losses: number;
3623
+ net_profit_display: string;
3624
+ net_profit_usd: number;
3625
+ pct: number;
3626
+ pending: number;
3627
+ roi_display: string;
3628
+ roi_pct: number;
3629
+ stake_usd: number;
3630
+ staked_usd: number;
3631
+ unit_score?: number;
3632
+ unit_score_display?: string;
3633
+ void: number;
3634
+ win_rate_display: string;
3635
+ wins: number;
3503
3636
  };
3504
- };
3505
- /** A derived 0xinsider correction to Polymarket's P&L, never a Polymarket value. Polymarket misbooks neg-risk conversions, in both directions: it puts cost on placeholder YES outcomes minted by a conversion and never books it as a loss (negative amount), and its position records leave out shares the wallet really got, such as YES minted by a conversion, so it books no P&L on them (positive amount). Per neg-risk market the wallet converted in, 0xinsider measures Polymarket's own activity cash against the sum of its position P&L, and sums the difference over every measured market whose shares did not move by direct transfer: transferred shares have no activity row, so such a market keeps Polymarket's figure and is counted in markets_excluded. It is published once every neg-risk market with a sports or esports event that the wallet converted in is measured and checked for transfers, and stays as last published until then; a market with no sports or esports event is not measured, and counts only when it was measured before (on the trader body, pnl.correction_pending says so); a sum under $1 either way publishes nothing. The body's own P&L fields keep Polymarket's figures; this object adds the amount and the corrected figures. Money is truncated toward zero to cents. */
3506
- export type PnlCorrection = {
3507
- /** The correction method. */
3508
- basis: "neg_risk_conversion_v1";
3509
- /** The correction in USD. Negative when Polymarket overstates the wallet. */
3510
- amount: number;
3511
- /** Polymarket's net realized P&L plus amount. Since 2026-10-22 the grade reads this figure's sports and esports share. Omitted when Polymarket's figure is. */
3512
- realized?: number;
3513
- /** Polymarket's net total P&L over every Polymarket market of the wallet, plus amount. Omitted when Polymarket's figure is, and on leaderboard entries. */
3514
- net_total?: number;
3515
- /** The newest measurement among the measured markets. */
3516
- as_of: string;
3517
- /** Neg-risk markets whose measurement amount sums. */
3518
- markets_measured: number;
3519
- /** Measured neg-risk markets left out because shares moved in or out of the wallet by direct transfer; they keep Polymarket's figure. Omitted when none. */
3520
- markets_excluded?: number;
3521
- };
3522
- export type Position = {
3523
- /** Composite prefixed ID `pos_<wallet>:<condition_id>:<outcome_index>`. */
3524
- id: string;
3525
- /** Provider discriminator. Polymarket only. */
3526
- platform: "polymarket";
3527
- /** Lowercased proxy wallet address. */
3528
- wallet: string;
3529
- /** Binary outcome side. Non-binary positions are not surfaced on V1. */
3530
- side: "YES" | "NO";
3531
- /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
3532
- token_id: string | null;
3533
- /** Live share count from the wallet_positions mirror. */
3534
- shares: number;
3535
- /** Volume-weighted entry price for this leg. */
3536
- avg_price?: number;
3537
- /** Current mark-to-market value in USD (always non-null on V1 — pre-reconcile rows are excluded). */
3637
+ market_expectations?: {
3638
+ as_of_date: string;
3639
+ price_basis: string;
3640
+ timezone: string;
3641
+ windows: ({
3642
+ clv_avg_display: string | null;
3643
+ clv_avg_pct: number | null;
3644
+ clv_avg_pp: number | null;
3645
+ clv_avg_pp_display: string | null;
3646
+ clv_measured: number;
3647
+ clv_missing: number;
3648
+ expected_wins: number | null;
3649
+ expected_wins_display: string | null;
3650
+ from_date: string | null;
3651
+ key: string;
3652
+ label: string;
3653
+ numeric_unavailable: boolean;
3654
+ priced_decided: number;
3655
+ through_date: string;
3656
+ units: number | null;
3657
+ units_display: string | null;
3658
+ units_z: number | null;
3659
+ units_z_display: string | null;
3660
+ unpriced_decided: number;
3661
+ wins: number;
3662
+ wins_z: number | null;
3663
+ wins_z_display: string | null;
3664
+ })[];
3665
+ };
3666
+ market_types?: {
3667
+ canonical_category?: string;
3668
+ clv_avg_display?: string;
3669
+ clv_avg_pct?: number;
3670
+ clv_avg_pp?: number;
3671
+ clv_avg_pp_display?: string;
3672
+ clv_measured: number;
3673
+ edge_display?: string;
3674
+ edge_pp?: number;
3675
+ key: string;
3676
+ label: string;
3677
+ losses: number;
3678
+ net_profit_display?: string;
3679
+ net_profit_usd?: number;
3680
+ pending: number;
3681
+ picks: number;
3682
+ priced_decided: number;
3683
+ priced_in_display?: string;
3684
+ priced_in_pct?: number;
3685
+ roi_display?: string;
3686
+ roi_pct?: number;
3687
+ settled: number;
3688
+ small_sample: boolean;
3689
+ staked_usd: number;
3690
+ unit_score?: number;
3691
+ unit_score_display?: string;
3692
+ void: number;
3693
+ win_rate_display?: string;
3694
+ win_rate_pct?: number;
3695
+ wins: number;
3696
+ }[];
3697
+ months?: {
3698
+ canonical_category?: string;
3699
+ clv_avg_display?: string;
3700
+ clv_avg_pct?: number;
3701
+ clv_avg_pp?: number;
3702
+ clv_avg_pp_display?: string;
3703
+ clv_measured: number;
3704
+ edge_display?: string;
3705
+ edge_pp?: number;
3706
+ key: string;
3707
+ label: string;
3708
+ losses: number;
3709
+ net_profit_display?: string;
3710
+ net_profit_usd?: number;
3711
+ pending: number;
3712
+ picks: number;
3713
+ priced_decided: number;
3714
+ priced_in_display?: string;
3715
+ priced_in_pct?: number;
3716
+ roi_display?: string;
3717
+ roi_pct?: number;
3718
+ settled: number;
3719
+ small_sample: boolean;
3720
+ staked_usd: number;
3721
+ unit_score?: number;
3722
+ unit_score_display?: string;
3723
+ void: number;
3724
+ win_rate_display?: string;
3725
+ win_rate_pct?: number;
3726
+ wins: number;
3727
+ }[];
3728
+ outcome_stats?: {
3729
+ concentration: {
3730
+ positive_wins: number;
3731
+ remaining_valued_decided: number;
3732
+ removed_wins: number;
3733
+ roi_without_top_wins_display: string | null;
3734
+ roi_without_top_wins_pct: number | null;
3735
+ target_wins: number;
3736
+ top_wins_share_display: string | null;
3737
+ top_wins_share_pct: number | null;
3738
+ valued_decided: number;
3739
+ };
3740
+ drawdown: {
3741
+ completed_days: number;
3742
+ current_days_below_peak: number | null;
3743
+ current_drawdown_display: string | null;
3744
+ current_drawdown_units: number | null;
3745
+ days_below_peak: number | null;
3746
+ excluded_days: number;
3747
+ from_date: string | null;
3748
+ longest_days_below_peak: number | null;
3749
+ longest_recovery_days: number | null;
3750
+ max_drawdown_display: string | null;
3751
+ max_drawdown_units: number | null;
3752
+ peak_date: string | null;
3753
+ peak_net_profit_usd: number | null;
3754
+ through_date: string | null;
3755
+ };
3756
+ profit_factor: {
3757
+ display: string | null;
3758
+ gross_loss_usd: number | null;
3759
+ gross_profit_usd: number | null;
3760
+ state: "empty" | "measured" | "no_losses" | "numeric_unavailable";
3761
+ value: number | null;
3762
+ valued_decided: number;
3763
+ };
3764
+ rolling: ({
3765
+ from_date: string | null;
3766
+ losses: number;
3767
+ roi_display: string | null;
3768
+ roi_pct: number | null;
3769
+ through_date: string | null;
3770
+ units: number | null;
3771
+ units_display: string | null;
3772
+ valued_decided: number;
3773
+ win_rate_display: string | null;
3774
+ win_rate_pct: number | null;
3775
+ window_size: number;
3776
+ wins: number;
3777
+ })[];
3778
+ };
3779
+ price_bands?: {
3780
+ canonical_category?: string;
3781
+ clv_avg_display?: string;
3782
+ clv_avg_pct?: number;
3783
+ clv_avg_pp?: number;
3784
+ clv_avg_pp_display?: string;
3785
+ clv_measured: number;
3786
+ edge_display?: string;
3787
+ edge_pp?: number;
3788
+ key: string;
3789
+ label: string;
3790
+ losses: number;
3791
+ net_profit_display?: string;
3792
+ net_profit_usd?: number;
3793
+ pending: number;
3794
+ picks: number;
3795
+ priced_decided: number;
3796
+ priced_in_display?: string;
3797
+ priced_in_pct?: number;
3798
+ roi_display?: string;
3799
+ roi_pct?: number;
3800
+ settled: number;
3801
+ small_sample: boolean;
3802
+ staked_usd: number;
3803
+ unit_score?: number;
3804
+ unit_score_display?: string;
3805
+ void: number;
3806
+ win_rate_display?: string;
3807
+ win_rate_pct?: number;
3808
+ wins: number;
3809
+ }[];
3810
+ records?: {
3811
+ best_day?: {
3812
+ date: string;
3813
+ date_display: string;
3814
+ losses: number;
3815
+ net_profit_display: string;
3816
+ net_profit_usd: number;
3817
+ picks: number;
3818
+ wins: number;
3819
+ };
3820
+ biggest_win?: {
3821
+ category: string;
3822
+ date: string;
3823
+ date_display: string;
3824
+ matchup: string;
3825
+ net_profit_display: string;
3826
+ net_profit_usd: number;
3827
+ };
3828
+ longest_losing_day_streak?: {
3829
+ days: number;
3830
+ end_date: string;
3831
+ net_profit_display: string;
3832
+ net_profit_usd: number;
3833
+ range_display: string;
3834
+ start_date: string;
3835
+ };
3836
+ longest_winning_day_streak?: {
3837
+ days: number;
3838
+ end_date: string;
3839
+ net_profit_display: string;
3840
+ net_profit_usd: number;
3841
+ range_display: string;
3842
+ start_date: string;
3843
+ };
3844
+ sweeps: {
3845
+ clean_sweeps: number;
3846
+ latest_clean_sweep?: {
3847
+ date: string;
3848
+ date_display: string;
3849
+ losses: number;
3850
+ wins: number;
3851
+ };
3852
+ latest_wipeout?: {
3853
+ date: string;
3854
+ date_display: string;
3855
+ losses: number;
3856
+ wins: number;
3857
+ };
3858
+ min_decided: number;
3859
+ wipeouts: number;
3860
+ };
3861
+ winning_days?: {
3862
+ flat: number;
3863
+ losing: number;
3864
+ settled: number;
3865
+ winning: number;
3866
+ winning_pct: number;
3867
+ winning_pct_display: string;
3868
+ };
3869
+ worst_day?: {
3870
+ date: string;
3871
+ date_display: string;
3872
+ losses: number;
3873
+ net_profit_display: string;
3874
+ net_profit_usd: number;
3875
+ picks: number;
3876
+ wins: number;
3877
+ };
3878
+ };
3879
+ sections: string[];
3880
+ series?: {
3881
+ date: string;
3882
+ hit_rate_pct: number;
3883
+ net_profit_usd: number;
3884
+ }[];
3885
+ sports?: {
3886
+ canonical_category?: string;
3887
+ clv_avg_display?: string;
3888
+ clv_avg_pct?: number;
3889
+ clv_avg_pp?: number;
3890
+ clv_avg_pp_display?: string;
3891
+ clv_measured: number;
3892
+ edge_display?: string;
3893
+ edge_pp?: number;
3894
+ key: string;
3895
+ label: string;
3896
+ losses: number;
3897
+ net_profit_display?: string;
3898
+ net_profit_usd?: number;
3899
+ pending: number;
3900
+ picks: number;
3901
+ priced_decided: number;
3902
+ priced_in_display?: string;
3903
+ priced_in_pct?: number;
3904
+ roi_display?: string;
3905
+ roi_pct?: number;
3906
+ settled: number;
3907
+ small_sample: boolean;
3908
+ staked_usd: number;
3909
+ unit_score?: number;
3910
+ unit_score_display?: string;
3911
+ void: number;
3912
+ win_rate_display?: string;
3913
+ win_rate_pct?: number;
3914
+ wins: number;
3915
+ }[];
3916
+ streaks?: {
3917
+ current?: number;
3918
+ current_day?: number;
3919
+ current_day_display?: string;
3920
+ current_display?: string;
3921
+ longest_loss: number;
3922
+ longest_win: number;
3923
+ };
3924
+ tiers?: {
3925
+ canonical_category?: string;
3926
+ clv_avg_display?: string;
3927
+ clv_avg_pct?: number;
3928
+ clv_avg_pp?: number;
3929
+ clv_avg_pp_display?: string;
3930
+ clv_measured: number;
3931
+ edge_display?: string;
3932
+ edge_pp?: number;
3933
+ key: string;
3934
+ label: string;
3935
+ losses: number;
3936
+ net_profit_display?: string;
3937
+ net_profit_usd?: number;
3938
+ pending: number;
3939
+ picks: number;
3940
+ priced_decided: number;
3941
+ priced_in_display?: string;
3942
+ priced_in_pct?: number;
3943
+ roi_display?: string;
3944
+ roi_pct?: number;
3945
+ settled: number;
3946
+ small_sample: boolean;
3947
+ staked_usd: number;
3948
+ unit_score?: number;
3949
+ unit_score_display?: string;
3950
+ void: number;
3951
+ win_rate_display?: string;
3952
+ win_rate_pct?: number;
3953
+ wins: number;
3954
+ }[];
3955
+ total_sides?: {
3956
+ canonical_category?: string;
3957
+ clv_avg_display?: string;
3958
+ clv_avg_pct?: number;
3959
+ clv_avg_pp?: number;
3960
+ clv_avg_pp_display?: string;
3961
+ clv_measured: number;
3962
+ edge_display?: string;
3963
+ edge_pp?: number;
3964
+ key: string;
3965
+ label: string;
3966
+ losses: number;
3967
+ net_profit_display?: string;
3968
+ net_profit_usd?: number;
3969
+ pending: number;
3970
+ picks: number;
3971
+ priced_decided: number;
3972
+ priced_in_display?: string;
3973
+ priced_in_pct?: number;
3974
+ roi_display?: string;
3975
+ roi_pct?: number;
3976
+ settled: number;
3977
+ small_sample: boolean;
3978
+ staked_usd: number;
3979
+ unit_score?: number;
3980
+ unit_score_display?: string;
3981
+ void: number;
3982
+ win_rate_display?: string;
3983
+ win_rate_pct?: number;
3984
+ wins: number;
3985
+ }[];
3986
+ view: string;
3987
+ voids?: {
3988
+ backed_price?: number;
3989
+ backed_side?: string;
3990
+ category?: string;
3991
+ matchup?: string;
3992
+ pick_date: string;
3993
+ pick_id: string;
3994
+ pick_rank: number;
3995
+ }[];
3996
+ selections?: {
3997
+ canonical_category?: string;
3998
+ clv_avg_display?: string;
3999
+ clv_avg_pct?: number;
4000
+ clv_avg_pp?: number;
4001
+ clv_avg_pp_display?: string;
4002
+ clv_measured: number;
4003
+ edge_display?: string;
4004
+ edge_pp?: number;
4005
+ key: string;
4006
+ label: string;
4007
+ losses: number;
4008
+ net_profit_display?: string;
4009
+ net_profit_usd?: number;
4010
+ pending: number;
4011
+ picks: number;
4012
+ priced_decided: number;
4013
+ priced_in_display?: string;
4014
+ priced_in_pct?: number;
4015
+ roi_display?: string;
4016
+ roi_pct?: number;
4017
+ settled: number;
4018
+ small_sample: boolean;
4019
+ staked_usd: number;
4020
+ unit_score?: number;
4021
+ unit_score_display?: string;
4022
+ void: number;
4023
+ win_rate_display?: string;
4024
+ win_rate_pct?: number;
4025
+ wins: number;
4026
+ }[];
4027
+ };
4028
+ /** A settled uncommitted pick's market, side and price. The same eight fields as PickOfTheDayCommitmentPayload, in the same key order, so a settled pick's side and price sit under payload whatever the entry's state. It is NOT a commitment: no hash was taken over it before the game, and it proves nothing about when the pick was made. */
4029
+ export type PickOfTheDayUncommittedPayload = {
4030
+ /** Frozen pre-game price of the backed side, 0..1, as the plain decimal text of the stored NUMERIC at full stored precision, trailing zeros included -- rendered exactly as the commitment payload renders it. */
4031
+ backed_price: string;
4032
+ /** Provider condition id of the backed market. */
4033
+ condition_id: string;
4034
+ /** Frozen provider kickoff, UTC, literal Z; null when no kickoff was frozen. Whole seconds render exactly as the commitment payload does; a sub-second instant keeps its fraction rather than being truncated, since nothing here is hashed. */
4035
+ kickoff: string | null;
4036
+ /** ET product day (YYYY-MM-DD). */
4037
+ pick_date: string;
4038
+ /** Index of the backed outcome within the market. */
4039
+ pick_outcome_index: 0 | 1;
4040
+ /** Frozen display label of the backed outcome. */
4041
+ pick_outcome_label: string;
4042
+ /** 1-based daily slot. */
4043
+ pick_rank: number;
4044
+ /** Provider platform. Always polymarket. */
4045
+ platform: "polymarket";
4046
+ };
4047
+ /** Provider-first sports context for a Pick of the Day market: team crests, league branding, and live score. Each team `logo` is a registered club crest or national flag as a same-origin path where one exists, and provider artwork otherwise. */
4048
+ export type PickSportsContext = {
4049
+ /** League or competition display name (e.g. "Premier League"). */
4050
+ league_name: string | null;
4051
+ /** Provider-owned event taxonomy from Gamma eventMetadata, joined in league · serie · tournament order with blanks and case-insensitive duplicates removed. A tennis qualifying match ends in ", Qualification", including an ATP Challenger qualifying match, which Gamma marks only in eventMetadata.tennisFixtureSource. Separate from league_name; omitted when the provider does not supply the metadata. */
4052
+ competition_label?: string;
4053
+ /** League logo URL (provider-owned). */
4054
+ league_logo: string | null;
4055
+ /** The team mapped to the market's YES outcome, or the parent-event home/first team when event_matchup is true. */
4056
+ yes_team: PickSportsTeam | null;
4057
+ /** The team mapped to the market's NO outcome, or the parent-event away/second team when event_matchup is true. */
4058
+ no_team: PickSportsTeam | null;
4059
+ /** Provider game identifier (Polymarket Gamma gameId); omitted when the provider supplies none. */
4060
+ game_id?: number;
4061
+ /** Always present. True when the two teams are the parent-event match identity for a teamless binary leg (e.g. a draw, totals, or prop market), not the market's own outcomes. */
4062
+ event_matchup: boolean;
4063
+ /** Present only alongside event_matchup: the event team the binary leg is about (provider group_item_title matched to a matchup team, e.g. Belgium for "Will Belgium win?"), i.e. the winner on a Yes resolution. Omitted for teamless legs (draw, totals, prop). */
4064
+ event_subject_team?: PickSportsTeam;
4065
+ /** The two teams as a single whole-game label, joined "<home> – <away>" (en-dash) in provider display order (e.g. "Portugal – Uzbekistan"). Composed server-side from the provider team names (no title/slug parsing). Present when both teams resolve a name; omitted for single-subject, teamless, or non-two-team contexts. */
4066
+ matchup_title?: string;
4067
+ };
4068
+ /** A single sports team or competitor in a Pick of the Day market's sports context. Identity and score fields are provider-owned and nullable. The structured score fields (`sets`, `format`, `sets_won`) and the tennis fields (`headshot`, `headshot_revision`, `tour`) are backend-owned and are OMITTED rather than null when they do not apply, so a consumer must treat an absent key and a null the same way. */
4069
+ export type PickSportsTeam = {
4070
+ /** Team display label as it appears on the market outcome (e.g. "Portugal"). */
4071
+ label: string | null;
4072
+ /** Abbreviated team label (e.g. "POR"). */
4073
+ short_label: string | null;
4074
+ /** The name to show for this team or competitor, the same on every surface (e.g. "UCF Knights", "Oklahoma City Thunder", "Portugal"). `label` keeps the market outcome's own spelling. */
4075
+ full_name: string | null;
4076
+ /** Provider team identifier (Polymarket /teams id). */
4077
+ provider_id: number | null;
4078
+ /** Team crest or flag URL. Official NFL (32), WNBA (15), NBA (30), NHL (32), and MLB (30) club crests use same-origin relative paths (`/api/sports/team-logos/{league}/{abbr}.svg?v=<content hash>`); resolve relative URLs against the API origin. Vendored soccer club crests use the same path with `.png`. National teams in the registered national-team competitions use the same path with `.svg`: the official national flag, drawn whole at its own aspect. Other teams use provider artwork, including country flags for tennis players. Novelty rows, and national-team rows that are not exactly one country, retain provider artwork. */
4079
+ logo: string | null;
4080
+ /** True when artwork measurements show that the team mark needs a light plate on a dark background. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured by the teams sync. Always sent; false when no current measurement marks the logo dark. */
4081
+ logo_mark_dark: boolean;
4082
+ /** Team brand color as a hex string (provider-owned). */
4083
+ color: string | null;
4084
+ /** Win-loss record as a display string (e.g. "12-4"). */
4085
+ record: string | null;
4086
+ /** Live or final score as a display string when the game is in play or settled. */
4087
+ score: string | null;
4088
+ /** Tennis player headshot URL, served same-origin. Present only for a tennis competitor the headshot resolver matched; absent for team sports and for unmatched players, where `logo` stays the fallback. */
4089
+ headshot?: string;
4090
+ /** Tennis tour this competitor belongs to. Present for every tennis entry whether or not `headshot` resolved, so a consumer can tell a tennis player with no photo from a non-tennis team. Absent for every other sport. Only `atp` and `wta` name a gender; the ITF World Tennis Tour runs men's and women's events and the provider does not say which, so `itf` means tennis with gender unknown. */
4091
+ tour?: "atp" | "wta" | "itf";
4092
+ /** Per-set score cells for this side, in set order. Backend-owned: render these rather than parsing `score`. Omitted entirely when the provider score is not a structured multi-set match or could not be parsed, so an absent array and an empty one carry the same meaning. */
4093
+ sets?: ScoreCell[];
4094
+ format?: ScoreFormat;
4095
+ /** Completed sets won by this side. Present only when both sides expose the same set columns, so a partially parsed scoreline reports no tally rather than a misleading one. */
4096
+ sets_won?: number;
4097
+ /** Optional monotonic photo revision for this tennis player, independent of the sports score revision. Legacy stored photos start at zero. Successful new or changed image bytes advance it; source checks and attribution changes do not. Compare only for the same tour and provider_id: a higher revision replaces the portrait, an equal revision may fill a missing portrait, and a lower revision must not replace a newer one. Absent when no photo resolved. */
4098
+ headshot_revision?: number;
4099
+ /** Optional latest retrieved ATP/WTA singles rank for this player. Absent for unranked, ambiguous, doubles, expired, or unavailable identities. This is not rank at match time. */
4100
+ ranking?: TennisRanking;
4101
+ /** True when artwork measurements show that the team mark disappears on a white background and needs a dark plate there: the light-background twin of logo_mark_dark. Vendored crest verdicts are tied to the exact asset bytes; provider artwork is measured on white by the teams sync. Always sent; false when no current measurement marks the logo light. */
4102
+ logo_mark_light: boolean;
4103
+ /** True when logo_mark_dark and logo_mark_light are both measurements of this exact logo URL, so their false means the mark is legible on that background. Every vendored crest is measured; a provider logo is measured once the teams sync has scored it, usually within a few hourly cycles of first appearing. Always sent; false while the logo is not measured yet. */
4104
+ logo_mark_measured: boolean;
4105
+ };
4106
+ export type PlatformCapabilities = {
4107
+ grade: PlatformCapabilityStatus;
4108
+ pnl: PlatformCapabilityStatus;
4109
+ strategy: PlatformCapabilityStatus;
4110
+ timeline: PlatformCapabilityStatus;
4111
+ /** The large-trade feed. Canonical key since #16304; whale_signal is its deprecated spelling, emitted beside it with the same value until its sunset on 2027-02-01 (#29352). */
4112
+ large_trades: PlatformCapabilityStatus;
4113
+ /**
4114
+ * Deprecated spelling of large_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read large_trades.
4115
+ * @deprecated
4116
+ */
4117
+ whale_signal: PlatformCapabilityStatus;
4118
+ suspicious_trades: PlatformCapabilityStatus;
4119
+ /**
4120
+ * Deprecated spelling of suspicious_trades, emitted beside it with the same value. Sunset 2027-02-01 (#29352): removed from V1 on that date; read suspicious_trades.
4121
+ * @deprecated
4122
+ */
4123
+ insider_radar: PlatformCapabilityStatus;
4124
+ market_snapshot: PlatformCapabilityStatus;
4125
+ };
4126
+ /** Every capability the API serves reports supported. The field names a per-capability status so a client can branch on coverage; no other value is emitted. */
4127
+ export type PlatformCapabilityStatus = "supported";
4128
+ export type Platforms = {
4129
+ platforms: {
4130
+ polymarket: PlatformCapabilities;
4131
+ };
4132
+ };
4133
+ /** A derived 0xinsider correction to Polymarket's P&L, never a Polymarket value. Polymarket misbooks neg-risk conversions, in both directions: it puts cost on placeholder YES outcomes minted by a conversion and never books it as a loss (negative amount), and its position records leave out shares the wallet really got, such as YES minted by a conversion, so it books no P&L on them (positive amount). Per neg-risk market the wallet converted in, 0xinsider measures Polymarket's own activity cash against the sum of its position P&L, and sums the difference over every measured market whose shares did not move by direct transfer: transferred shares have no activity row, so such a market keeps Polymarket's figure and is counted in markets_excluded. It is published once every neg-risk market with a sports or esports event that the wallet converted in is measured and checked for transfers, and stays as last published until then; a market with no sports or esports event is not measured, and counts only when it was measured before (on the trader body, pnl.correction_pending says so); a sum under $1 either way publishes nothing. The body's own P&L fields keep Polymarket's figures; this object adds the amount and the corrected figures. Money is truncated toward zero to cents. */
4134
+ export type PnlCorrection = {
4135
+ /** The correction method. */
4136
+ basis: "neg_risk_conversion_v1";
4137
+ /** The correction in USD. Negative when Polymarket overstates the wallet. */
4138
+ amount: number;
4139
+ /** Polymarket's net realized P&L plus amount. Since 2026-10-22 the grade reads this figure's sports and esports share. Omitted when Polymarket's figure is. */
4140
+ realized?: number;
4141
+ /** Polymarket's net total P&L over every Polymarket market of the wallet, plus amount. Omitted when Polymarket's figure is, and on leaderboard entries. */
4142
+ net_total?: number;
4143
+ /** The newest measurement among the measured markets. */
4144
+ as_of: string;
4145
+ /** Neg-risk markets whose measurement amount sums. */
4146
+ markets_measured: number;
4147
+ /** Measured neg-risk markets left out because shares moved in or out of the wallet by direct transfer; they keep Polymarket's figure. Omitted when none. */
4148
+ markets_excluded?: number;
4149
+ };
4150
+ export type Position = {
4151
+ /** Composite prefixed ID `pos_<wallet>:<condition_id>:<outcome_index>`. */
4152
+ id: string;
4153
+ /** Provider discriminator. Polymarket only. */
4154
+ platform: "polymarket";
4155
+ /** Lowercased proxy wallet address. */
4156
+ wallet: string;
4157
+ /** Binary outcome side. Non-binary positions are not surfaced on V1. */
4158
+ side: "YES" | "NO";
4159
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
4160
+ token_id: string | null;
4161
+ /** Live share count from the wallet_positions mirror. */
4162
+ shares: number;
4163
+ /** Volume-weighted entry price for this leg. */
4164
+ avg_price?: number;
4165
+ /** Current mark-to-market value in USD (always non-null on V1 — pre-reconcile rows are excluded). */
3538
4166
  current_value_usd: number;
3539
4167
  initial_value_usd?: number;
3540
4168
  /** Unrealized P&L for the open position (Polymarket `cashPnl`). */
@@ -3983,48 +4611,88 @@ export type SnapshotState = {
3983
4611
  /** When this body's source read started, the clock finality is judged on. null for a body stored before that clock was recorded. */
3984
4612
  source_read_started_at: string | null;
3985
4613
  };
4614
+ /** One sport's skill leaderboard, or one league's. Every figure on a row is the wallet's record in this sport or league, except grade, the wallet's all-time grade, and volume (see volume_scope). */
3986
4615
  export type SportLeaderboard = {
4616
+ /** The latest time any wallet's record on this board was recomputed. The sport ranking reruns hourly, a league ranking about once a day. null when the board has no rows. */
3987
4617
  as_of: string | null;
4618
+ /** The canonical sport the slug resolved to, for example Soccer or Basketball. null when no wallet has a record under it; rows is then empty. */
3988
4619
  category: string | null;
4620
+ /** The mean edge over every wallet in the field whose price_edge.status is ranked, held ones included: the value each row's edge_skill is pulled toward. null when no wallet's edge is ranked. */
3989
4621
  edge_average: number | null;
4622
+ /** The league this board ranks; null on a sport board. */
3990
4623
  league: {
4624
+ /** The league's display name. */
3991
4625
  name: string;
4626
+ /** Wallets the league board's edge sort ranks with no hold. */
3992
4627
  ranked_traders: number;
4628
+ /** The league's slug under its sport, for example premier-league or cs2. */
3993
4629
  slug: string;
3994
4630
  } | null;
4631
+ /** The requested limit after clamping to 1..100 (default 20). rows holds fewer when the board has fewer wallets. */
3995
4632
  limit: number;
4633
+ /** Settled markets of $20 or more a wallet needs in the sport or league to be on the board. */
3996
4634
  min_resolved: number;
4635
+ /** The head of the board, in sort order. Every figure is the wallet's record in this sport or league, except grade (all-time) and volume (see volume_scope). */
3997
4636
  rows: ({
4637
+ /** Lowercase proxy wallet. */
3998
4638
  address: string;
4639
+ /** What the wallet paid, USD, for the settled markets pnl counts. null when any of them has no stored cost, never a partial sum. */
3999
4640
  cost: number | null;
4641
+ /** Why sort=edge sets aside an edge whose status is ranked. category_loss: the wallet's realized P&L in this sport or league is zero or below. record_incomplete: the wallet's stored sports and esports P&L runs more than 5% of its cost ahead of Polymarket's own figure, so settled losing markets are likely missing from its record. A held row keeps its price_edge and edge_skill and sorts after the ranked rows on sort=edge. null when nothing holds the edge, and always null unless price_edge.status is ranked. */
4000
4642
  edge_hold: "category_loss" | "record_incomplete" | null;
4643
+ /** price_edge.edge pulled toward edge_average by the share of the record that is noise: a short record moves most of the way to the average, a long one keeps nearly all of its own edge. The value sort=edge orders by when edge_hold is null. null unless price_edge.status is ranked. */
4001
4644
  edge_skill: number | null;
4645
+ /** The wallet's all-time grade, S to F, the one every route serves. It is led by realized profit across all of the wallet's sports and esports markets, not this sport's or league's, so a wallet can lead a board on in-sport P&L and still grade F. Every letter is listed: the board ranks the in-sport record and does not filter on the grade. null when the wallet has no grade. */
4002
4646
  grade: "S" | "A" | "B" | "C" | "D" | "F" | null;
4647
+ /** trd_0x..., the id the trader routes accept. */
4003
4648
  id: string;
4649
+ /** The wallet's last trade on a settled market of $20 or more in this sport or league. */
4004
4650
  last_category_trade_at: string | null;
4651
+ /** Markets n_resolved counts that settled at a realized loss. A market that broke even counts in neither wins nor losses. */
4005
4652
  losses: number;
4653
+ /** The wallet's settled markets of $20 or more in this sport or league; at least min_resolved. */
4006
4654
  n_resolved: number;
4655
+ /** Provider platform. Always polymarket. */
4007
4656
  platform: "polymarket";
4657
+ /** Realized P&L, USD, across the markets n_resolved counts: this sport or league only, not the wallet's whole record. The value sort=pnl orders by. */
4008
4658
  pnl: number | null;
4659
+ /** Edge over the price paid in this sport or league: how often the side the wallet bought won, minus the average price it paid. Probabilities throughout: edge 0.03 is 3 percentage points. A market bought on both sides counts by its shares. null when the wallet has no priced settled market here. */
4009
4660
  price_edge: {
4661
+ /** Mean entry price paid, 0-1. */
4010
4662
  avg_price: number;
4663
+ /** hit_rate minus avg_price, full precision, before any shrink. edge_skill is the shrunk value. */
4011
4664
  edge: number;
4665
+ /** The low end of edge's 95% range: edge minus 1.96 times the square root of avg_price * (1 - avg_price) / markets. Not a sort key: sort=edge orders by edge_skill. */
4012
4666
  edge_lower: number;
4667
+ /** Share of those markets whose bought side won, 0-1. A market bought on both sides adds the winning side's share of the shares bought. */
4013
4668
  hit_rate: number;
4669
+ /** Settled markets of $20 or more in this sport or league at a known entry price that the edge is measured over. */
4014
4670
  markets: number;
4671
+ /** Whether the edge ranks. ranked: at least 30 such markets, and the share of the decided ones that made money at settlement within 10 points of the win rate here. too_few_markets: fewer than 30. sample_mismatch: that share is more than 10 points away, so these markets do not describe the wallet's record. Only a ranked edge with a null edge_hold orders on sort=edge. */
4015
4672
  status: "ranked" | "too_few_markets" | "sample_mismatch";
4016
4673
  } | null;
4674
+ /** 1-based position on this board under sort. A page of limit rows is the head of the board. */
4017
4675
  rank: number;
4676
+ /** pnl / cost, a fraction: 0.12 is 12%. null when cost is null. */
4018
4677
  roi: number | null;
4678
+ /** The wallet's Polymarket username; null when it has none. */
4019
4679
  username: string | null;
4680
+ /** USD, measured as volume_scope says. On a sport board: the wallet's volume across all its sports and esports markets, the profile's Volume traded, not this sport's alone. null on every league board row: no per-league volume is stored. */
4020
4681
  volume: number | null;
4682
+ /** wins / (wins + losses) in this sport or league, 0-1: 0.6 is 60%. null when no market was decided. */
4021
4683
  win_rate: number | null;
4684
+ /** The lower bound of the 95% Wilson interval on win_rate, 0-1: the value sort=win_rate orders by, so a short perfect record does not outrank a long strong one. null with win_rate. */
4022
4685
  win_rate_wilson_lb: number | null;
4686
+ /** Markets n_resolved counts that settled at a realized profit. */
4023
4687
  wins: number;
4024
4688
  })[];
4689
+ /** The order rows are in. edge: by edge_skill, with every wallet whose edge is not ranked, or is held, after the ranked ones. pnl: by realized P&L in the sport or league. win_rate: by the Wilson lower bound of the win rate. */
4025
4690
  sort: "edge" | "pnl" | "win_rate";
4691
+ /** The board's sport slug, for example soccer, basketball or esports. An alias in the path, such as nba or cs2, reads as its sport's slug. */
4026
4692
  sport: string;
4693
+ /** Wallets with at least min_resolved settled markets in the sport or league and a trade, in any market, in the last 180 days: the field rows is the head of. */
4027
4694
  total_traders: number;
4695
+ /** What each row's volume measures. sports_and_esports: the wallet's volume across all its sports and esports markets, not this sport's or league's alone. */
4028
4696
  volume_scope: "sports_and_esports";
4029
4697
  };
4030
4698
  export type SuspiciousTrade = {
@@ -4226,6 +4894,18 @@ export type Trader = {
4226
4894
  /** Current evidence for observed and known categories (expand=categories or expand[]=categories). Omitted unless expanded. Includes insufficient, stale, unknown and degraded rows; absence of a category is not proof of skill. The global grade is unchanged. Sports and esports only (#28827): a category outside them is omitted, as on GET /api/v1/trader/{address}/categories. */
4227
4895
  category_records?: CategorySkillV2[];
4228
4896
  category_skill_model?: CategorySkillModelReadiness;
4897
+ /** Edge over the price paid: the profile's Edge badge and the leaderboard's Edge measure (#32622). Present on every read of a wallet with at least one settled sports or esports market of $20 or more at a known entry price; omitted for a wallet with none, where there is nothing to measure. */
4898
+ price_edge?: TraderPriceEdge;
4899
+ /** The profile's strategy measures over the wallet's sports and esports markets: P&L and win rate by UTC hour, hold-time and first-trade-hour bands, position sizes with category concentration, and entry-price buckets (#32622). Present only when expand=breakdowns or expand[]=breakdowns is requested, on GET /api/v1/trader/{address} only: POST /api/v1/traders/batch refuses the expand. Computed on the read from the wallet's whole sports and esports history, so a large wallet can take seconds; a read that cannot finish answers 503 with Retry-After. */
4900
+ breakdowns?: TraderBreakdowns;
4901
+ };
4902
+ /** The profile's strategy measures (expand=breakdowns, #32622), the same figures as the wallet profile's Insights and Performance breakdown cards. Every figure counts the wallet's sports and esports markets only, from the same read the profile makes. */
4903
+ export type TraderBreakdowns = {
4904
+ hourly_performance: TraderHourlyPerformance;
4905
+ time_breakdowns: TraderTimeBreakdowns;
4906
+ /** Position sizes and category concentration. null when the wallet has no sports or esports position with trades, or its stored markets carry no freshness clock yet. */
4907
+ risk_metrics: TraderRiskMetrics | null;
4908
+ entry_price_analysis: TraderEntryPriceAnalysis;
4229
4909
  };
4230
4910
  export type TraderCategoryRecord = {
4231
4911
  /** Canonical category bucket, for example Soccer, Esports, Tennis. Esports is one bucket, and the Esports record carries its per-game records in games. */
@@ -4297,6 +4977,56 @@ export type TraderContext = {
4297
4977
  /** Human-readable statement of the point-in-time snapshot semantics (data_as_of is the open-position clock -- the latest /positions snapshot, else the last completed sync; the snapshot advances only open positions, so resolved counts and win rate can include settled markets recorded after the last full sync; native realized P&L follows its accounting snapshot -- not a live feed; re-fetch for fresher data). */
4298
4978
  freshness_note: string;
4299
4979
  };
4980
+ /** Results by the entry price the wallet paid for the side it held, over its settled sports and esports positions with a held entry price. coverage counts the settled positions the buckets leave out, and why. */
4981
+ export type TraderEntryPriceAnalysis = {
4982
+ /** One bucket per price band that has a market, in bucket_order. */
4983
+ buckets: TraderEntryPriceBucket[];
4984
+ /** The bucket with the highest win rate among buckets of at least 3 markets. null when no bucket has 3. */
4985
+ best_bucket: string | null;
4986
+ /** The bucket with the lowest win rate among buckets of at least 3 markets. null when no bucket has 3. */
4987
+ worst_bucket: string | null;
4988
+ /** What the buckets cover (since 2026-11-03, #32671). */
4989
+ coverage: TraderEntryPriceCoverage;
4990
+ };
4991
+ /** One entry-price band. Each measure is an analytic value: read state before value. */
4992
+ export type TraderEntryPriceBucket = {
4993
+ /** The band: $0.00-$0.19 (any price below $0.20, sub-cent fills included), $0.20-$0.39, $0.40-$0.59, $0.60-$0.79 or $0.80-$0.99. Until 2026-11-03 the first band was $0.01-$0.19 and sub-cent fills had no bucket (#32671). */
4994
+ bucket: string;
4995
+ /** Display position, 0 first, from the lowest price up. */
4996
+ bucket_order: number;
4997
+ /** Markets in the band. */
4998
+ markets: AnalyticInteger;
4999
+ /** Of those, the markets that made money. */
5000
+ wins: AnalyticInteger;
5001
+ /** wins over decided markets (a nonzero P&L), as a percentage 0-100. */
5002
+ win_rate: AnalyticNumber;
5003
+ /** Realized P&L of the band's markets, USD. */
5004
+ total_pnl: AnalyticNumber;
5005
+ /** Mean realized P&L of a market in the band, USD. */
5006
+ avg_pnl: AnalyticNumber;
5007
+ };
5008
+ /** The settled sports and esports positions the entry-price section reads. The buckets' markets plus every unbucketed row's are settled_markets, and their realized P&L sums to settled_pnl. settled_pnl adds up the wallet's per-market realized P&L, so it differs from pnl.in_scope.realized_pnl, which is Polymarket's published sports and esports P&L with a share of the wallet's rebates. */
5009
+ export type TraderEntryPriceCoverage = {
5010
+ /** Settled sports and esports positions: bucketed_markets plus every unbucketed row's markets. */
5011
+ settled_markets: number;
5012
+ /** Realized P&L of those positions, USD. */
5013
+ settled_pnl: number;
5014
+ /** Positions in a bucket: the sum of buckets[].markets. */
5015
+ bucketed_markets: number;
5016
+ /** Realized P&L of the bucketed positions, USD: the sum of buckets[].total_pnl. */
5017
+ bucketed_pnl: number;
5018
+ /** The settled positions the buckets leave out: one row for each reason that has a position, ordered by reason. Empty when the buckets hold every settled position. */
5019
+ unbucketed: TraderEntryPriceUnbucketed[];
5020
+ };
5021
+ /** Settled positions with no entry-price bucket, for one reason. */
5022
+ export type TraderEntryPriceUnbucketed = {
5023
+ /** two_sided: both outcomes bought at a price, a hedged book with no single side. held_side_unpriced: one outcome has a recorded price, but the wallet's remaining shares are on the other. no_entry_price: no outcome has a recorded entry price. freshness_unknown: a bucket whose rows carry no freshness clock yet. */
5024
+ reason: "two_sided" | "held_side_unpriced" | "no_entry_price" | "freshness_unknown";
5025
+ /** Positions left out for this reason. */
5026
+ markets: number;
5027
+ /** Their realized P&L, USD. */
5028
+ total_pnl: number;
5029
+ };
4300
5030
  export type TraderEsportsGameRecord = {
4301
5031
  /** The game, by the same name every holder chip carries in category_win_rate_game: LoL, CS2, Dota 2, Valorant, Call of Duty, Honor of Kings, Mobile Legends: Bang Bang, Overwatch, Rainbow Six Siege, Rocket League or StarCraft II. Match a chip to this row by string equality. */
4302
5032
  game: string;
@@ -4470,6 +5200,36 @@ export type TraderGradeAt = {
4470
5200
  source_observed_by: string | null;
4471
5201
  } | null;
4472
5202
  };
5203
+ /** P&L and win rate by the UTC hour of the wallet's first trade in each settled sports or esports market. */
5204
+ export type TraderHourlyPerformance = {
5205
+ /** One entry per UTC hour that has a settled market; an hour with none is absent. */
5206
+ entries: ({
5207
+ /** UTC hour of the first trade, 0-23. */
5208
+ hour: number;
5209
+ /** Settled markets first traded in this hour. */
5210
+ markets: number;
5211
+ /** Of those, the markets that made money at settlement. */
5212
+ wins: number;
5213
+ /** wins over the decided markets (settled with a nonzero P&L), as a percentage 0-100. 0 when no market of the hour is decided: read it with wins and markets. */
5214
+ win_rate: number;
5215
+ /** Realized P&L of those markets, USD. */
5216
+ total_pnl: number;
5217
+ /** total_pnl over markets, USD. */
5218
+ avg_pnl: number;
5219
+ })[];
5220
+ /** The hour with the highest win_rate. null when no entry exists. */
5221
+ best_hour: number | null;
5222
+ /** best_hour's win_rate, percentage 0-100. null exactly when best_hour is. */
5223
+ best_win_rate: number | null;
5224
+ /** The hour with the lowest win_rate. null when no entry exists. */
5225
+ worst_hour: number | null;
5226
+ /** worst_hour's win_rate, percentage 0-100. null exactly when worst_hour is. */
5227
+ worst_win_rate: number | null;
5228
+ /** best_win_rate minus worst_win_rate, percentage points. null when either is null. */
5229
+ spread_pp: number | null;
5230
+ /** true when at least 12 hours have markets and every one of them has the same P&L sign, so the hour-to-hour spread says little about timing. */
5231
+ is_approximate: boolean;
5232
+ };
4473
5233
  /** A trader's sports and esports daily P&L object. `id`, `freshness_at`, `series_status` and `realized` are always present. The five sections -- `entries`, `stats`, `monthly`, `year_totals`, `drawdown` -- are present unless the request's `sections` parameter excluded them, so a request that sends no `sections` always carries all five. An excluded section is absent from the object, never null and never an empty array. While `series_status` is `pending` the sections are empty and never mean zero. */
4474
5234
  export type TraderPnl = {
4475
5235
  /** Prefixed trader ID (`trd_...`). */
@@ -4623,6 +5383,40 @@ export type TraderPnlInScope = {
4623
5383
  /** When the record behind these figures was computed. */
4624
5384
  as_of: string;
4625
5385
  };
5386
+ /** Edge over the price paid (#32270, #32622): how often the side a wallet bought won, minus the average price it paid, over its settled sports and esports markets of $20 or more at a known entry price. Probabilities throughout: edge 0.012 is 1.2 percentage points. The same figures as LeaderboardPriceEdge, plus the shrunk edge the profile badge and the leaderboard show. No hold: a hold is a fact of a leaderboard row, not of the wallet. */
5387
+ export type TraderPriceEdge = {
5388
+ /** Settled sports and esports markets of $20 or more at a known entry price that the edge is measured over. */
5389
+ markets: number;
5390
+ /** Share of those markets whose bought side won, 0-1. */
5391
+ hit_rate: number;
5392
+ /** Mean entry price paid, 0-1. */
5393
+ avg_price: number;
5394
+ /** hit_rate minus avg_price, full precision, before any shrink. */
5395
+ edge: number;
5396
+ /** Whether the edge ranks. ranked: at least 30 such markets, and the share of the decided ones that made money at settlement within 10 points of the win rate over the same markets. too_few_markets: fewer than 30. sample_mismatch: that share is more than 10 points away, so these markets do not describe the wallet's record. */
5397
+ status: "ranked" | "too_few_markets" | "sample_mismatch";
5398
+ /** The edge the profile badge shows and the leaderboard ranks: edge pulled toward field_average by how short the record is. A short record moves most of the way to the average; a long one keeps nearly all of its own edge. Present only when status is ranked. */
5399
+ shrunk_edge?: number;
5400
+ /** The mean edge of every ranked wallet that traded in the last 180 days, the value shrunk_edge is pulled toward. Present only with shrunk_edge. */
5401
+ field_average?: number;
5402
+ };
5403
+ /** Position sizes over the wallet's sports and esports positions with trades, and how concentrated its volume is across categories. Each measure is an analytic value: read state before value. The four size measures are not_computed while any position's cost is unknown; the counts are always measured. */
5404
+ export type TraderRiskMetrics = {
5405
+ /** Mean cost basis of a position, USD. */
5406
+ avg_position_size: AnalyticNumber;
5407
+ /** Median cost basis of a position, USD. */
5408
+ median_position_size: AnalyticNumber;
5409
+ /** Largest cost basis of a position, USD. */
5410
+ max_position_size: AnalyticNumber;
5411
+ /** Population standard deviation of the cost basis, USD. */
5412
+ position_size_stddev: AnalyticNumber;
5413
+ /** Sports and esports positions with trades. */
5414
+ total_positions: number;
5415
+ /** Positions whose cost is more than twice the mean. */
5416
+ large_position_count: number;
5417
+ /** Herfindahl index of the wallet's volume across sports and esports categories: each category's share of the volume, squared and summed. 1.0 is a single category; lower is more spread. not_computed while any category's cost is unknown, and no value without volume. */
5418
+ concentration: AnalyticNumber;
5419
+ };
4626
5420
  /** Lossless counterparts for trader statistics. The object is present exactly when stats.total_volume is. */
4627
5421
  export type TraderStatsExact = {
4628
5422
  /** stats.total_volume as an exact decimal: the sports and esports USD volume, the sum of every stored trade day's `trader_trade_daily_rollups.in_scope_volume_total` (#29830). Polymarket's full-history wallet-wide user volume before 2026-10-27. */
@@ -4635,6 +5429,30 @@ export type TraderSyncedData = {
4635
5429
  /** Proxy wallet address. */
4636
5430
  wallet: string;
4637
5431
  };
5432
+ /** One band of a time breakdown. */
5433
+ export type TraderTimeBreakdownBand = {
5434
+ /** The band's label. */
5435
+ category_value: string;
5436
+ /** Markets with a realized P&L in the band. */
5437
+ n_markets: number;
5438
+ /** Resolved markets that made money over resolved markets with a nonzero P&L, 0-1. null when none is decided. */
5439
+ win_rate: number | null;
5440
+ /** total_pnl over n_markets, USD. */
5441
+ expectancy: number | null;
5442
+ /** Gross profit over gross loss. null when the band has no loss. */
5443
+ profit_factor: number | null;
5444
+ /** Realized P&L of the band's markets, USD. */
5445
+ total_pnl: number | null;
5446
+ };
5447
+ /** The hold-time and first-trade-hour bands of the profile's Performance breakdown card, over the wallet's sports and esports markets with a realized P&L. */
5448
+ export type TraderTimeBreakdowns = {
5449
+ /** One row per band of time from the wallet's first to its last trade in a market: < 1h, 1h – 1d, 1 – 3d, 3 – 7d, 1 – 4w, > 4w. A band with no market is absent. */
5450
+ by_duration: TraderTimeBreakdownBand[];
5451
+ /** One row per four-hour UTC band of the wallet's first trade in a market: 00-03, 04-07, 08-11, 12-15, 16-19, 20-23. A band with no market is absent. */
5452
+ by_hour_bucket: TraderTimeBreakdownBand[];
5453
+ /** One-line summaries keyed by breakdown (by_duration, by_hour_bucket), from bands of at least 5 markets with a known P&L. A key is present only when there is a summary. */
5454
+ insights: Record<string, string>;
5455
+ };
4638
5456
  /** Field-level trust metadata returned only when GET /api/v1/trader/{address} includes expand=trust. */
4639
5457
  export type TraderTrust = {
4640
5458
  /** Since 2026-10-27 always not_computed: pnl.total is retired and never sent (#29830). The key stays so the object keeps its shape. */
@@ -5254,11 +6072,64 @@ export interface OperationData {
5254
6072
  getMarketTopHolders: MarketTopHolders;
5255
6073
  getMarketWalletsInOut: MarketWalletsInOut;
5256
6074
  getMonthlyReportSnapshot: ReportSnapshot;
5257
- getPickOfTheDay: PickOfTheDay | PickOfTheDayNoEntitledPicks;
5258
- getPickOfTheDayArchive: PickOfTheDayArchive;
6075
+ getPickOfTheDay: PickOfTheDay | PickOfTheDayNoEntitledPicks | {
6076
+ disclaimer?: string;
6077
+ locked_picks?: {
6078
+ pick_rank: number;
6079
+ required_tier: string;
6080
+ }[];
6081
+ pick_count: number;
6082
+ pick_date: string;
6083
+ picks: {
6084
+ backed_price?: number;
6085
+ category?: string;
6086
+ clv_pct?: number;
6087
+ clv_status?: string;
6088
+ display_category?: string;
6089
+ event_slug?: string;
6090
+ game_ended?: boolean;
6091
+ game_started?: boolean;
6092
+ holder_count?: number;
6093
+ is_free_selection: boolean;
6094
+ matchup?: string;
6095
+ outcome?: string;
6096
+ pick_id: string;
6097
+ pick_outcome_label?: string;
6098
+ polymarket_url?: string;
6099
+ publication_order: number;
6100
+ release_at?: string;
6101
+ return_usd?: number;
6102
+ stake_usd?: number;
6103
+ token_id?: string;
6104
+ top_grade?: string;
6105
+ unit_score?: number;
6106
+ }[];
6107
+ proof_pending_picks?: ({
6108
+ is_free_selection: boolean;
6109
+ kickoff?: string;
6110
+ pick_id: string;
6111
+ pick_rank: number;
6112
+ publication_order: number;
6113
+ release_at: string;
6114
+ retry_at: string;
6115
+ supersedes_pick_id: string | null;
6116
+ })[];
6117
+ scheduled_picks?: ({
6118
+ is_free_selection: boolean;
6119
+ kickoff: string;
6120
+ pick_id: string;
6121
+ pick_rank: number;
6122
+ publication_order: number;
6123
+ release_at: string;
6124
+ supersedes_pick_id: string | null;
6125
+ })[];
6126
+ state: string;
6127
+ view: string;
6128
+ };
6129
+ getPickOfTheDayArchive: PickOfTheDayArchive | PickOfTheDayArchiveSummary;
5259
6130
  getPickOfTheDayLedger: PickOfTheDayLedger;
5260
6131
  getPickOfTheDayLedgerEntry: PickOfTheDayLedgerEntry;
5261
- getPickOfTheDayStats: PickOfTheDayStats;
6132
+ getPickOfTheDayStats: PickOfTheDayStats | PickOfTheDayStatsSections;
5262
6133
  getPlatforms: Platforms;
5263
6134
  getPositionTimeline: PositionTimelineEvent[];
5264
6135
  getPositionTimelineById: PositionTimelineEvent[];
@@ -5601,7 +6472,7 @@ export interface OperationQuery {
5601
6472
  createWebhookVerificationAttempt: Record<string, never>;
5602
6473
  deleteWebhook: Record<string, never>;
5603
6474
  exploreMarkets: {
5604
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Facet values are returned as the canonical bucket. Sports and esports only (#27411): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6475
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Facet values are returned as the canonical bucket. Sports and esports only (#27411): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). The Sports facet counts that catch-all category alone. */
5605
6476
  category?: string;
5606
6477
  /** Filter by market status. A market is closed once Polymarket has closed trading or it has resolved, and active otherwise; all returns both. */
5607
6478
  status?: "active" | "closed" | "all";
@@ -5638,7 +6509,7 @@ export interface OperationQuery {
5638
6509
  getEdgeHunter: {
5639
6510
  /** Response mode. board preserves the full quoted board; signals exposes ranked records and category evidence; observations exposes cohort measurements and accountable funnel evidence. Defaults to board. */
5640
6511
  view?: "board" | "signals" | "observations";
5641
- /** Legacy canonical bucket alias, now accepted in every view. Provider aliases canonicalize: NFL reaches Football and EPL reaches Soccer. Use leagues for a league-specific selection. An unmappable non-sport category returns an empty result and echoes category non_sport. Combines with other selection axes using AND. */
6512
+ /** Legacy canonical bucket alias, now accepted in every view. Provider aliases canonicalize: NFL reaches Football and EPL reaches Soccer. Use leagues for a league-specific selection. The word sports, in any casing, reads as kind=sports, every sport but Esports, as category=sports does on every other route (#32720): the response echoes kind sports beside category sports, and with kind=esports it returns 400 with param category. Any other unmappable non-sport category returns an empty result and echoes category non_sport. Combines with other selection axes using AND. */
5642
6513
  category?: string;
5643
6514
  /** Required for view=observations; wider_holder, in_play or emerging_pile. Rejected for board and signals. wider_holder covers pregame markets that view=signals does not list at its widest selection (horizon_hours=48, min_grade=B, no selector), so until kickoff a market is read in one view or the other. A market view=signals lists leaves wider_holder as primary_slate_candidate, and is a wider_holder candidate again in the first refresh after view=signals stops listing it; signals_as_of names the view=signals snapshot each refresh read. Each refresh evaluates at most 8 markets per sport and cohort, wider_holder by soonest kickoff (most graded holders first among equal kickoffs) and in_play by most graded holders, so a market among a sport's 8 soonest stays evaluated until its game starts. wider_holder also evaluates up to 8 more markets per sport that kick off within 24 hours, most graded holders first, so the most-held markets appear up to a day before kickoff. Each of these keeps its place in later refreshes until its game starts while its holder page still shows a card or could not be read, so a more-held market waits for a free place instead of displacing it. Each row's admitted_by names its place, most_held or soonest_kickoff. The rest count in coverage.capacity_limited_markets. Emerging pile is a wider-holder projection with sharp_pct in [0.75,0.85), complete holder scans and future kickoff, not an independent population or arrival history. */
5644
6515
  cohort?: "wider_holder" | "in_play" | "emerging_pile";
@@ -5676,8 +6547,10 @@ export interface OperationQuery {
5676
6547
  trader?: string;
5677
6548
  /** Only trades on this market: the raw provider condition_id or its mkt_-prefixed id. Bound to the cursor. */
5678
6549
  condition_id?: string;
5679
- /** Only trades by wallets at this grade or better (S best), read from the wallet's newest ranking at request time; a wallet with no grade never passes. Bound to the cursor. */
6550
+ /** Only trades by wallets at this grade or better (S best), read from the wallet's newest ranking at request time; a wallet with no grade never passes. For the grade the wallet held when the trade filled, send min_grade_at_trade instead. Bound to the cursor. */
5680
6551
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
6552
+ /** Only trades whose grade_at_trade, the grade the wallet held when the trade filled, is at this grade or better (S best). Only a trade whose grade at the fill is graded passes, so a trade before 2026-09-19T23:00Z, or one made while the wallet's grade was changing, never does. The same basis as min_grade_at_trade on GET /api/v1/large-trades, GET /api/v1/stream and webhook trade_filters. Bound to the cursor: switching between min_grade and min_grade_at_trade is a filter change and answers cursor_expired. Sending it with min_grade, or an invalid grade, returns HTTP 400. */
6553
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
5681
6554
  /** Only trades of at least this USD amount. Decimal and scientific query spellings normalize exactly to cents, rounding half away from zero; maximum 1e15 USD. Pass the dataset continuation decimal string unchanged to preserve the bound. Bound to the cursor. */
5682
6555
  min_size?: number | string;
5683
6556
  /** Backward-compatible alias for expand. Repeatable: trade. */
@@ -5744,11 +6617,29 @@ export interface OperationQuery {
5744
6617
  getPickOfTheDay: {
5745
6618
  /** A product day (America/New_York) in YYYY-MM-DD format, on or before today. Omit it, or send today, for the current read. A past day with no published pick returns 404 not_found with error.param=date; a date after today, or a value that is not a date, returns 400 bad_request with error.param=date. */
5746
6619
  date?: string;
6620
+ /** full (default) is the whole recorded set: every pick with its holders, lead backer, sports context, thesis and entry_authorization, and the top-level copy of the first pick. summary returns pick_date, pick_count, the disclaimer once, and each entitled pick's identity, side, price, result, return and grade (pick_id, publication_order, is_free_selection, matchup, category, display_category, event_slug, polymarket_url, token_id, pick_outcome_label, outcome, backed_price, stake_usd, return_usd, unit_score, top_grade, holder_count, clv_status, clv_pct, release_at, game_started, game_ended), with the same scheduled_picks, proof_pending_picks and locked_picks. The locked-only state=none body is the same in both views. Any other value returns 400 bad_request with error.param=view. */
6621
+ view?: "full" | "summary";
6622
+ /** One entitled published pick of the day, by its stable decimal-string pick_id. The body carries that pick once, as picks[0], beside state, pick_date and pick_count=1. It leaves out the top-level copy of the first pick that a set read without pick_id repeats, and scheduled_picks, proof_pending_picks and locked_picks. Pair it with date for a past day's pick. A pick_id that is not among the day's entitled published picks returns 404 not_found with error.param=pick_id; one whose holder proof is not readable yet returns 503 read_model_warming with Retry-After; a value that is not a positive canonical decimal returns 400 bad_request with error.param=pick_id. */
6623
+ pick_id?: string;
6624
+ };
6625
+ getPickOfTheDayArchive: {
6626
+ /** full (default) is every row with every field, plus days and hit_rate with its per-pick series. summary returns view, hit_rate without series, one page of short rows (pick_id, pick_date, publication_order, is_free_selection, matchup, display_category, pick_outcome_label, outcome, top_grade, backed_price, unit_score, clv_pct, backed_side_locked, required_tier) and page; it always pages, 50 rows unless limit says otherwise. Any other value returns 400 bad_request with error.param=view. */
6627
+ view?: "full" | "summary";
6628
+ /** Rows per page of picks, 1 to 200, default 50. An integer outside that range is clamped into it, like every list limit, and X-Effective-Query reports the limit applied; a value that is not an integer returns 400 invalid_query. On view=full, sending limit or cursor pages picks and adds page, while days and hit_rate still describe the whole record; with neither, the response is the whole record. */
6629
+ limit?: number;
6630
+ /** The page.next_cursor of the previous page: the rows after it, newest first. A cursor is a position in the record, so a pick published while you page does not shift later pages. A value this route did not return returns 400 bad_request with error.param=cursor. */
6631
+ cursor?: string;
5747
6632
  };
5748
- getPickOfTheDayArchive: Record<string, never>;
5749
6633
  getPickOfTheDayLedger: Record<string, never>;
5750
6634
  getPickOfTheDayLedgerEntry: Record<string, never>;
5751
- getPickOfTheDayStats: Record<string, never>;
6635
+ getPickOfTheDayStats: {
6636
+ /** full (default) is every section. summary returns view, sections and every section except the five that grow with the record: series, days, categories, months and voids. In summary and sections bodies hit_rate carries no series; series is its own top-level section. Ignored when sections is sent. Any other value returns 400 bad_request with error.param=view. */
6637
+ view?: "full" | "summary";
6638
+ /** Exactly the sections to return, in the body's order whatever the request order. Repeatable and comma-separated: hit_rate, series, market_expectations, outcome_stats, days, categories, sports, tiers, selections, months, price_bands, market_types, total_sides, streaks, records, voids. The body names them in sections and carries view=sections. An unrecognized name returns 400 bad_request with error.param=sections rather than being ignored. */
6639
+ sections?: ("hit_rate" | "series" | "market_expectations" | "outcome_stats" | "days" | "categories" | "sports" | "tiers" | "selections" | "months" | "price_bands" | "market_types" | "total_sides" | "streaks" | "records" | "voids")[];
6640
+ /** Backward-compatible bracket alias for sections, for clients that emit array keys. Repeatable and comma-separated, with the same names. */
6641
+ "sections[]"?: ("hit_rate" | "series" | "market_expectations" | "outcome_stats" | "days" | "categories" | "sports" | "tiers" | "selections" | "months" | "price_bands" | "market_types" | "total_sides" | "streaks" | "records" | "voids")[];
6642
+ };
5752
6643
  getPlatforms: Record<string, never>;
5753
6644
  getPositionTimeline: {
5754
6645
  /** Market condition_id. One timeline per (trader, market). */
@@ -5795,8 +6686,10 @@ export interface OperationQuery {
5795
6686
  event?: string;
5796
6687
  /** 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. */
5797
6688
  condition_id?: string;
5798
- /** 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. */
6689
+ /** 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). On a LargeTradeInsertedV2 frame that field is grade, the wallet's grade when the trade was published: seconds after the fill for a live trade, hours after it for a backfilled one, so it is not always the grade the trade filled under. For that, send min_grade_at_trade instead. 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. */
5799
6690
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
6691
+ /** Filter LargeTradeInsertedV2 frames to trades whose grade_at_trade, the grade the trader held when the trade filled, is at or above this minimum (S is best). Only a frame whose grade_at_trade_status is graded can match. The same basis as min_grade_at_trade on GET /api/v1/large-trades and on webhook trade_filters. Other event types are excluded when set. Sending it with min_grade, or an invalid grade, returns HTTP 400. */
6692
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
5800
6693
  /** 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. */
5801
6694
  wallet?: string;
5802
6695
  /** 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. */
@@ -5804,15 +6697,15 @@ export interface OperationQuery {
5804
6697
  };
5805
6698
  getSuspiciousTrade: Record<string, never>;
5806
6699
  getTrader: {
5807
- /** Backward-compatible alias for expand. Repeatable: strategy, categories, trust. quant_metrics is accepted and returns nothing since 2026-10-27. */
5808
- "expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
5809
- /** Include heavy fields and trust metadata. Repeatable: strategy, categories, trust. quant_metrics is accepted and returns nothing since 2026-10-27. */
5810
- expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
6700
+ /** Backward-compatible alias for expand. Repeatable: strategy, categories, trust, breakdowns. quant_metrics is accepted and returns nothing since 2026-10-27. */
6701
+ "expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust" | "breakdowns")[];
6702
+ /** Include heavy fields and trust metadata. Repeatable: strategy, categories, trust, breakdowns. breakdowns adds the profile's strategy measures (Trader.breakdowns), computed on the read, and is served on this route only. quant_metrics is accepted and returns nothing since 2026-10-27. */
6703
+ expand?: ("strategy" | "categories" | "quant_metrics" | "trust" | "breakdowns")[];
5811
6704
  /** Opt into a whole-response freshness ceiling in seconds. The server returns 200 only when data_quality.status is fresh or stale 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. */
5812
6705
  max_age_s?: number;
5813
6706
  };
5814
6707
  getTraderCategoryRecords: {
5815
- /** 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 sports or esports category the wallet has no record in answers 200 with an empty records array, never 404. Sports and esports only (#27311): a category outside them, or a value that reaches no category, returns 400 bad_request with param category and names the accepted buckets. */
6708
+ /** 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 sports or esports category the wallet has no record in answers 200 with an empty records array, never 404. Sports and esports only (#27311): a category outside them, or a value that reaches no category, returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
5816
6709
  category?: string;
5817
6710
  };
5818
6711
  getTraderContext: Record<string, never>;
@@ -5933,7 +6826,7 @@ export interface OperationQuery {
5933
6826
  cursor?: string;
5934
6827
  /** Minimum position value in USD. Raises the feed's own floor of 50,000 USD; a smaller value does not lower it. */
5935
6828
  min_size?: number;
5936
- /** One RFC 4180 CSV record of exact current provider-backed market_canonical.category values. Legacy unquoted lists such as NBA,WNBA remain valid; values containing commas, quotes, or newlines are CSV-quoted. Matching is case-insensitive. Malformed quoted input fails closed as one unknown exact category. A value outside sports and esports returns 400 bad_request with param=category (#27305), as on GET /api/v1/markets/explore. */
6829
+ /** One RFC 4180 CSV record of exact current provider-backed market_canonical.category values. Legacy unquoted lists such as NBA,WNBA remain valid; values containing commas, quotes, or newlines are CSV-quoted. Matching is case-insensitive. Malformed quoted input fails closed as one unknown exact category. A value outside sports and esports returns 400 bad_request with param=category (#27305), as on GET /api/v1/markets/explore. The word sports, in any casing, names every sport and returns 400 bad_request with param category, because this filter takes one category: omit category for every sports and esports market, or name one sport (#32657). */
5937
6830
  category?: string;
5938
6831
  /** Minimum trader grade. Matched against the trader.grade each row returns, the wallet's current grade, so every row listed shows a grade at or above this floor. */
5939
6832
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
@@ -5967,10 +6860,12 @@ export interface OperationQuery {
5967
6860
  condition_id?: string;
5968
6861
  /** Trader wallet address, timestamp-suffixed wallet alias, username, or trd_-prefixed trader ID, resolved against the traders table. Unknown traders return an empty list. */
5969
6862
  trader?: string;
5970
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6863
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
5971
6864
  category?: string;
5972
- /** Minimum trader grade as of today (trader.grade), not at trade time. On a historical window it selects wallets by a grade they may have earned after the trade; for a point-in-time rule filter on trader.grade_at_trade instead. A means S or A, B means S, A or B. */
6865
+ /** Minimum trader grade as of today (trader.grade), not at trade time. On a historical window it selects wallets by a grade they may have earned after the trade; for a point-in-time rule send min_grade_at_trade instead, which filters on trader.grade_at_trade. A means S or A, B means S, A or B. */
5973
6866
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
6867
+ /** Minimum grade the trader held when the trade filled (trader.grade_at_trade). Only rows whose trader.grade_at_trade_status is graded can match, so a trade before 2026-09-19T23:00Z, or one made while the wallet's grade was changing, never does. The same basis as min_grade_at_trade on GET /api/v1/large-trades, GET /api/v1/stream and webhook trade_filters, so a history read and a stream with the same floor agree. Applies to both sorts and beside condition_id, event_slug, trader and from/to. Sending it with min_grade is 400. A means S or A, B means S, A or B. */
6868
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
5974
6869
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
5975
6870
  suspicious_only?: boolean;
5976
6871
  /** Filter by whale_alerts.platform. all is equivalent to omitted. */
@@ -5993,10 +6888,12 @@ export interface OperationQuery {
5993
6888
  cursor?: string;
5994
6889
  /** Minimum trade size in USD. */
5995
6890
  min_size?: number;
5996
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6891
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
5997
6892
  category?: string;
5998
- /** Minimum trader grade. */
6893
+ /** Minimum trader grade now (trader.grade), the wallet's grade when this page is read, not when the trade filled. A wallet re-graded after a trade enters or leaves the result, so a catch-up read can disagree with GET /api/v1/stream and webhooks. For the grade at the fill, send min_grade_at_trade instead. A means S or A, B means S, A or B. */
5999
6894
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
6895
+ /** Minimum grade the trader held when the trade filled (trader.grade_at_trade). Only rows whose trader.grade_at_trade_status is graded can match, so a trade before 2026-09-19T23:00Z, or one made while the wallet's grade was changing, never does. The same basis as min_grade_at_trade on GET /api/v1/stream and on webhook trade_filters, so a client that catches up here and then streams gets one answer. Applies to every path: recent, since, sort=market_volume_share, condition_id and event_slug. Sending it with min_grade is 400. A means S or A, B means S, A or B. */
6896
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
6000
6897
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
6001
6898
  suspicious_only?: boolean;
6002
6899
  /** 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. */
@@ -6015,7 +6912,7 @@ export interface OperationQuery {
6015
6912
  limit?: number;
6016
6913
  /** Opaque lbv1_ pagination cursor from a prior response. It binds the finite score/address boundary to the committed leaderboard generation and the effective category/strategy filters, and on a sorted page to its sort, dir and activity. A cursor from another sort or dir is a 400 bad_request on cursor; one from another activity, category, strategy or generation is cursor_expired. Legacy, malformed, non-finite, and unsupported-version cursors are rejected. */
6017
6914
  cursor?: string;
6018
- /** Filter by category: a sport or esports bucket. Values are matched to canonical category buckets: league values fold into their sport (NBA and NCAAB into Basketball, NFL into Football). Mapped buckets are case-insensitive; passthrough buckets (Cricket, Sports) match case-sensitively against the provider-native bucket key, so use exact casing. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6915
+ /** Filter by category: a sport or esports bucket, matched case-insensitively. League values fold into their sport (NBA and NCAAB into Basketball, NFL into Football). Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
6019
6916
  category?: string;
6020
6917
  /** Filter by observed trading style. Current styles: two_sided, category_focused, high_activity, diversified, mixed, unclassified. Current styles count the wallet's sports and esports markets only. The ten archetype keys retired on 2026-10-01 (accumulator, algo_trader, arbitrageur, directional, event_driven, market_maker, momentum, scalper, speculator, swing_trader) are still accepted and match no wallet. Style describes recorded behavior; grade measures performance. */
6021
6918
  strategy?: "category_focused" | "diversified" | "high_activity" | "mixed" | "two_sided" | "unclassified";
@@ -6036,7 +6933,7 @@ export interface OperationQuery {
6036
6933
  consistency?: "live" | "snapshot";
6037
6934
  /** 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. */
6038
6935
  min_size?: number;
6039
- /** Exact match against provider-backed market_canonical.category. Sports and esports only (#27311): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6936
+ /** Exact match against provider-backed market_canonical.category. Sports and esports only (#27311): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, names every sport and returns 400 bad_request with param category, because this filter takes one category: omit category for every sports and esports market, or name one sport (#32657). */
6040
6937
  category?: string;
6041
6938
  /** Scope to one market. Accepts the raw provider condition_id or the mkt_-prefixed market id emitted by V1 responses. Combine with min_size=0 for every reconciled position in that market; an unknown id or a resolved market returns []. A market outside sports and esports returns 404 not_found with error.reason=market_out_of_scope (#27311). Without condition_id the board and wallet reads list sports and esports markets only. */
6042
6939
  condition_id?: string;
@@ -6056,7 +6953,7 @@ export interface OperationQuery {
6056
6953
  limit?: number;
6057
6954
  /** Opaque cursor from previous response's next_cursor. Encodes the first-page as_of timestamp, normalized effective filters, ranking and aggregate collection revisions, plus the last row's absolute net flow and condition_id. A changed filter or collection returns cursor_expired; request the first page again. */
6058
6955
  cursor?: string;
6059
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6956
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
6060
6957
  category?: string;
6061
6958
  /** Filter by source platform. all is a request-side no-op. */
6062
6959
  platform?: "polymarket" | "all";
@@ -6076,7 +6973,7 @@ export interface OperationQuery {
6076
6973
  limit?: number;
6077
6974
  /** Opaque cursor from previous response's next_cursor. Encodes the first-page as_of timestamp, normalized effective filters, ranking and aggregate collection revisions, plus the last row's absolute net flow and condition_id. A changed filter or collection returns cursor_expired; request the first page again. */
6078
6975
  cursor?: string;
6079
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
6976
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27306): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
6080
6977
  category?: string;
6081
6978
  /** Filter by source platform. all is a request-side no-op. */
6082
6979
  platform?: "polymarket" | "all";
@@ -6144,10 +7041,12 @@ export interface OperationQuery {
6144
7041
  condition_id?: string;
6145
7042
  /** Trader wallet address, timestamp-suffixed wallet alias, or username resolved against the traders table. Unknown traders return an empty list. */
6146
7043
  trader?: string;
6147
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
7044
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
6148
7045
  category?: string;
6149
7046
  /** Minimum trader grade. */
6150
7047
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
7048
+ /** Minimum grade the trader held when the trade filled (trader.grade_at_trade). Only rows whose trader.grade_at_trade_status is graded can match, so a trade before 2026-09-19T23:00Z, or one made while the wallet's grade was changing, never does. The same basis as min_grade_at_trade on GET /api/v1/large-trades, GET /api/v1/stream and webhook trade_filters, so a history read and a stream with the same floor agree. Applies to both sorts and beside condition_id, event_slug, trader and from/to. Sending it with min_grade is 400. A means S or A, B means S, A or B. */
7049
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
6151
7050
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
6152
7051
  suspicious_only?: boolean;
6153
7052
  /** Filter by whale_alerts.platform. all is equivalent to omitted. */
@@ -6170,10 +7069,12 @@ export interface OperationQuery {
6170
7069
  cursor?: string;
6171
7070
  /** Minimum trade size in USD. */
6172
7071
  min_size?: number;
6173
- /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
7072
+ /** Filter by market category (case-insensitive). A canonical bucket name (e.g. Basketball) matches every provider member that folds into it (NBA, WNBA, NCAAB); a raw provider value also resolves to its bucket. Sports and esports only (#27430): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, matches every sport but Esports, the provider's catch-all Sports category (cycling, lacrosse) included: use esports for Esports alone, or omit category for both (#32657). */
6174
7073
  category?: string;
6175
- /** Minimum trader grade as of today (trader.grade). A means S or A, B means S, A or B. */
7074
+ /** Minimum trader grade now (trader.grade), the wallet's grade when this page is read, not when the trade filled. A wallet re-graded after a trade enters or leaves the result, so a catch-up read can disagree with GET /api/v1/stream and webhooks. For the grade at the fill, send min_grade_at_trade instead. A means S or A, B means S, A or B. */
6176
7075
  min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
7076
+ /** Minimum grade the trader held when the trade filled (trader.grade_at_trade). Only rows whose trader.grade_at_trade_status is graded can match, so a trade before 2026-09-19T23:00Z, or one made while the wallet's grade was changing, never does. The same basis as min_grade_at_trade on GET /api/v1/stream and on webhook trade_filters, so a client that catches up here and then streams gets one answer. Applies to every path: recent, since, sort=market_volume_share, condition_id and event_slug. Sending it with min_grade is 400. A means S or A, B means S, A or B. */
7077
+ min_grade_at_trade?: "S" | "A" | "B" | "C" | "D" | "F";
6177
7078
  /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
6178
7079
  suspicious_only?: boolean;
6179
7080
  /** 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. */
@@ -6207,7 +7108,7 @@ export interface OperationQuery {
6207
7108
  cursor?: string;
6208
7109
  /** Filter by market status. A market is closed once Polymarket has closed trading or it has resolved, and active otherwise; all returns both. */
6209
7110
  status?: "active" | "closed" | "all";
6210
- /** Filter by category. Sports and esports only (#27411): a category outside them returns 400 bad_request with param category and names the accepted buckets. */
7111
+ /** Filter by category. Sports and esports only (#27411): a category outside them returns 400 bad_request with param category and names the accepted buckets. The word sports, in any casing, names every sport and returns 400 bad_request with param category, because this filter takes one category: omit category for every sports and esports market, or name one sport (#32657). */
6211
7112
  category?: string;
6212
7113
  };
6213
7114
  submitTraderExport: {
@@ -6500,7 +7401,7 @@ export interface OperationBody {
6500
7401
  batchGetTraders: {
6501
7402
  /** Trader identities to resolve in input order. */
6502
7403
  traders: string[];
6503
- /** Shared expand flags applied to every trader item. */
7404
+ /** Shared expand flags applied to every trader item. breakdowns is refused with 400 (param expand): it computes on the read per wallet, so GET /api/v1/trader/{address} serves it one wallet at a time. */
6504
7405
  expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
6505
7406
  };
6506
7407
  cancelTraderExport: never;
@@ -7026,6 +7927,7 @@ export interface OperationResponse {
7026
7927
  /** Total matching rows when the read model exposes a count; the key is absent when it does not. */
7027
7928
  total?: number;
7028
7929
  meta: ResponseMeta;
7930
+ summary?: LeaderboardSummary;
7029
7931
  };
7030
7932
  listLeaderboardLeagues: {
7031
7933
  object: "leaderboard_leagues";