@0xinsider/mcp 1.2.3 → 2.0.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 (66) hide show
  1. package/README.md +93 -1
  2. package/dist/catalog.generated.d.ts +4 -0
  3. package/dist/catalog.generated.d.ts.map +1 -1
  4. package/dist/catalog.generated.js +5 -0
  5. package/dist/catalog.generated.js.map +1 -1
  6. package/dist/cli-lib.d.ts.map +1 -1
  7. package/dist/cli-lib.js +9 -5
  8. package/dist/cli-lib.js.map +1 -1
  9. package/dist/cli.js +6 -1
  10. package/dist/cli.js.map +1 -1
  11. package/dist/constants.d.ts +1 -1
  12. package/dist/constants.js +1 -1
  13. package/dist/product-cli/errors.d.ts +7 -0
  14. package/dist/product-cli/errors.d.ts.map +1 -0
  15. package/dist/product-cli/errors.js +13 -0
  16. package/dist/product-cli/errors.js.map +1 -0
  17. package/dist/product-cli/index.d.ts +4 -0
  18. package/dist/product-cli/index.d.ts.map +1 -0
  19. package/dist/product-cli/index.js +372 -0
  20. package/dist/product-cli/index.js.map +1 -0
  21. package/dist/product-cli/oauth.d.ts +10 -0
  22. package/dist/product-cli/oauth.d.ts.map +1 -0
  23. package/dist/product-cli/oauth.js +245 -0
  24. package/dist/product-cli/oauth.js.map +1 -0
  25. package/dist/product-cli/storage.d.ts +20 -0
  26. package/dist/product-cli/storage.d.ts.map +1 -0
  27. package/dist/product-cli/storage.js +149 -0
  28. package/dist/product-cli/storage.js.map +1 -0
  29. package/dist/sdk/client.d.ts +765 -0
  30. package/dist/sdk/client.d.ts.map +1 -0
  31. package/dist/sdk/client.js +974 -0
  32. package/dist/sdk/client.js.map +1 -0
  33. package/dist/sdk/errors.d.ts +313 -0
  34. package/dist/sdk/errors.d.ts.map +1 -0
  35. package/dist/sdk/errors.js +521 -0
  36. package/dist/sdk/errors.js.map +1 -0
  37. package/dist/sdk/index.d.ts +26 -0
  38. package/dist/sdk/index.d.ts.map +1 -0
  39. package/dist/sdk/index.js +25 -0
  40. package/dist/sdk/index.js.map +1 -0
  41. package/dist/sdk/pagination.d.ts +76 -0
  42. package/dist/sdk/pagination.d.ts.map +1 -0
  43. package/dist/sdk/pagination.js +106 -0
  44. package/dist/sdk/pagination.js.map +1 -0
  45. package/dist/sdk/schema.d.ts +2372 -0
  46. package/dist/sdk/schema.d.ts.map +1 -0
  47. package/dist/sdk/schema.js +7 -0
  48. package/dist/sdk/schema.js.map +1 -0
  49. package/dist/sdk/stream.d.ts +182 -0
  50. package/dist/sdk/stream.d.ts.map +1 -0
  51. package/dist/sdk/stream.js +391 -0
  52. package/dist/sdk/stream.js.map +1 -0
  53. package/dist/sdk/webhooks.d.ts +163 -0
  54. package/dist/sdk/webhooks.d.ts.map +1 -0
  55. package/dist/sdk/webhooks.js +122 -0
  56. package/dist/sdk/webhooks.js.map +1 -0
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +2 -1
  59. package/dist/server.js.map +1 -1
  60. package/dist/tools/get-trending-wallets.js +4 -4
  61. package/dist/tools/get-trending-wallets.js.map +1 -1
  62. package/dist/tools/read-parity.d.ts +1 -0
  63. package/dist/tools/read-parity.d.ts.map +1 -1
  64. package/dist/tools/read-parity.js +27 -0
  65. package/dist/tools/read-parity.js.map +1 -1
  66. package/package.json +6 -3
@@ -0,0 +1,2372 @@
1
+ export type AccountIdentity = {
2
+ object: "account";
3
+ data: {
4
+ user_id: number;
5
+ credential_id: number;
6
+ credential_kind: "api_key" | "oauth_grant";
7
+ /** Approved OAuth scopes; null for full developer-key access. */
8
+ scopes: string[] | null;
9
+ };
10
+ meta: ResponseMeta;
11
+ };
12
+ /** A sandbox key and the path to live access (#13959). Nothing is stored: the key cannot be listed or revoked and does not expire. Register again for a new one. */
13
+ export type AgentRegistration = {
14
+ /** The sandbox key. Send it as Authorization: Bearer <api_key> to the sandbox. The last 8 hex characters are a checksum (the first 4 bytes of SHA-256 over the rest of the key), so the sandbox can tell a mistyped key from a real one. It is not a secret and unlocks no production data. */
15
+ api_key: string;
16
+ /** Always false: this key never reaches live data. */
17
+ livemode: false;
18
+ environment: "sandbox";
19
+ created_at: string;
20
+ sandbox: {
21
+ /** The sandbox V1 base URL. Every documented operation answers here with example data. */
22
+ api_base_url: string;
23
+ /** A read to send with the key. */
24
+ first_request_url: string;
25
+ /** The OpenAPI document, served by the sandbox. */
26
+ openapi_url: string;
27
+ };
28
+ /** What live data needs, and where each credential comes from. Both need a person: an account with an active Pro subscription. */
29
+ live_access: {
30
+ /** The production V1 base URL. */
31
+ api_base_url: string;
32
+ /** What a live credential needs, in one sentence. */
33
+ requirement: string;
34
+ /** Where a signed-in Pro user creates a live key (oxi_sk_live_). */
35
+ api_keys_url: string;
36
+ /** RFC 8414 authorization server metadata, for an OAuth 2.1 grant the user approves. */
37
+ oauth_authorization_server_metadata_url: string;
38
+ /** RFC 7591 dynamic client registration for public OAuth clients. */
39
+ oauth_registration_endpoint: string;
40
+ /** The Pro plan. */
41
+ pricing_url: string;
42
+ /** The authentication walkthrough for agents. */
43
+ auth_guide_url: string;
44
+ };
45
+ };
46
+ export type ApiDiscovery = {
47
+ /** Canonical API origin for public V1 requests. */
48
+ api_base_url: string;
49
+ /** Full agent-readable API reference. */
50
+ docs_url: string;
51
+ /** Canonical web-origin OpenAPI JSON document. */
52
+ openapi_url: string;
53
+ /** Unauthenticated API health endpoint. */
54
+ health_url: string;
55
+ authentication: "Bearer API key required for data endpoints; discovery (/api/v1), health, /api/v1/platforms, and the MCP handshake (initialize, ping, tools/list on /api/v1/mcp) are public. A 401 carries WWW-Authenticate with the resource_metadata URL.";
56
+ /** RFC 9728 protected-resource metadata for the API origin: the document every V1 401 names in its WWW-Authenticate challenge (resource, bearer_methods_supported, resource_documentation). The remote MCP server has its own document at /.well-known/oauth-protected-resource/api/v1/mcp. */
57
+ protected_resource_metadata_url: string;
58
+ /** The complete authenticated route index: one entry per authenticated route this spec documents, in "<METHOD> <path>" form, not a representative subset. GET /api/v1 is the unauthenticated entrypoint an agent hits first, so it hands back the whole authenticated surface rather than a sample the caller would have to guess around. The example on GET /api/v1 is abridged for readability -- the live response returns all of them. Kept in lockstep with this spec by review: it is a hand-maintained const in backend/src/api_v1/discovery.rs and no automated check compares the two, so treat this spec as authoritative if they ever disagree. */
59
+ authenticated_routes: string[];
60
+ };
61
+ export type ApiError = {
62
+ object: "error";
63
+ error: {
64
+ code: "bad_request" | "invalid_api_key" | "subscription_required" | "forbidden" | "not_found" | "account_locked" | "rate_limited" | "rate_limit_unavailable" | "internal_error";
65
+ message: string;
66
+ doc_url?: string | null;
67
+ param?: string | null;
68
+ /** The recommended next request instant (RFC3339), always in the future. Present on every retryable error: `pick_not_released`, `rate_limited`, `rate_limit_unavailable`, and `read_model_warming`. Omitted otherwise. The absolute twin of `Retry-After`; prefer the header for the sleep duration. For `pick_not_released`, the earliest of the next scheduled release, the next automatic selector attempt, the operating-window start, or about 60 seconds. See that response. */
69
+ retry_at?: string | null;
70
+ /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is outside the HOT/WARM sync tiers -- stop asking for this wallet. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. */
71
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive";
72
+ };
73
+ meta: ResponseMeta;
74
+ };
75
+ export type ApiErrorBody = {
76
+ code: "bad_request" | "invalid_api_key" | "subscription_required" | "forbidden" | "not_found" | "account_locked" | "rate_limited" | "rate_limit_unavailable" | "internal_error";
77
+ message: string;
78
+ doc_url?: string | null;
79
+ param?: string | null;
80
+ /** The recommended next retry instant (RFC3339). Present on every retryable error (reason=pick_not_released, code=rate_limited, code=rate_limit_unavailable, reason=read_model_warming) and omitted otherwise. Always in the future. For pick_not_released: before the 11:00 UTC operating-window start, before a selected pick's stored release, or after a skipped day, it names the automatic system's next boundary. While no candidate exists in the live window it normally names the persisted next automatic selector attempt. Every value is advisory under supported operator actions: manual publication, release-time override, or admin generation can make a pick available first. When the automatic schedule is absent/due or a pick is overdue it degrades to ~60s. Schedule one request and do not poll. Prefer Retry-After for the duration because it is immune to client clock skew. */
81
+ retry_at?: string | null;
82
+ /** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is outside the HOT/WARM sync tiers -- stop asking for this wallet. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. */
83
+ reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive";
84
+ };
85
+ export type BatchMarketIntelItem = {
86
+ /** Zero-based request index. Duplicate inputs keep separate result rows. */
87
+ index: number;
88
+ input: string;
89
+ status: "ok" | "error";
90
+ data?: MarketIntel;
91
+ error?: ApiErrorBody;
92
+ };
93
+ export type BatchRateLimitMeta = {
94
+ basis: "batch_items_per_minute";
95
+ limit: number;
96
+ remaining: number;
97
+ /** Unix timestamp when the batch item window resets. */
98
+ reset: number;
99
+ };
100
+ export type BatchResponseMeta = {
101
+ request_id: string;
102
+ cached: boolean;
103
+ total_items: number;
104
+ successful_items: number;
105
+ failed_items: number;
106
+ /** Number of batch item units reserved before execution. */
107
+ request_cost: number;
108
+ rate_limit: BatchRateLimitMeta;
109
+ };
110
+ export type BatchTraderItem = {
111
+ /** Zero-based request index. Duplicate inputs keep separate result rows. */
112
+ index: number;
113
+ input: string;
114
+ status: "ok" | "error";
115
+ data?: Trader;
116
+ error?: ApiErrorBody;
117
+ };
118
+ /** One bucketed OHLC price candle. Prices are in provider [0, 1] units, truncated to 4 decimals at the rendering edge. */
119
+ export type Candle = {
120
+ /** Bucket-start unix epoch (seconds): UTC midnight for 1d, the ISO-week Monday's UTC midnight for 1w. */
121
+ t: number;
122
+ /** Open price in provider [0, 1] units (first observed point in the bucket). */
123
+ o: number;
124
+ /** High price in provider [0, 1] units (max observed in the bucket). */
125
+ h: number;
126
+ /** Low price in provider [0, 1] units (min observed in the bucket). */
127
+ l: number;
128
+ /** Close price in provider [0, 1] units (last observed point in the bucket). */
129
+ c: number;
130
+ };
131
+ export type ContentSearchResult = {
132
+ /** Backend-owned stable editorial content identifier. */
133
+ content_id: string;
134
+ /** Editorial content kind. */
135
+ kind: "learn" | "glossary" | "comparison" | "research" | "strategy";
136
+ /** Backend-owned content slug. */
137
+ slug: string;
138
+ /** Editorial title. */
139
+ title: string;
140
+ /** Search-result excerpt. */
141
+ excerpt: string;
142
+ /** Canonical first-party content URL. */
143
+ url: string;
144
+ };
145
+ export type CounterpartyAnalysis = {
146
+ status: "available" | "partial" | "unavailable";
147
+ unavailable_reason?: string | null;
148
+ /** Deterministic immutable membership snapshot for this detail response. */
149
+ snapshot_id?: string | null;
150
+ /** Stable digest binding page cursors to one snapshot and execution set. */
151
+ analysis_id?: string | null;
152
+ execution_count: number;
153
+ available_execution_count: number;
154
+ unavailable_execution_count: number;
155
+ executions: CounterpartyExecution[];
156
+ /** Stable cursor after the last execution included in the bounded inline page. */
157
+ executions_next_cursor?: string | null;
158
+ };
159
+ export type CounterpartyExecution = {
160
+ execution_id: string;
161
+ exchange_family: "ctf_v2" | "neg_risk_ctf_v2";
162
+ transaction_hash: string;
163
+ orders_matched_log_index: number;
164
+ taker: CounterpartyParticipant;
165
+ makers: CounterpartyParticipant[];
166
+ /** Stable cursor after the last maker included in the bounded inline page. */
167
+ makers_next_cursor?: string | null;
168
+ };
169
+ export type CounterpartyMakerPage = {
170
+ analysis_id: string;
171
+ snapshot_id: string;
172
+ execution_id: string;
173
+ items: CounterpartyParticipant[];
174
+ /** Cursor bound to the analysis, execution, last full-denominator share total, and wallet. */
175
+ next_cursor?: string | null;
176
+ };
177
+ export type CounterpartyMatchBreakdown = {
178
+ match_type: "COMPLEMENTARY" | "MINT" | "MERGE";
179
+ maker_fill_count: number;
180
+ /** Exact decimal shares. */
181
+ filled_shares: string;
182
+ };
183
+ export type CounterpartyParticipant = {
184
+ counterparty_key: string;
185
+ /** Lowercase Polygon wallet from the exact OrderFilled log. */
186
+ execution_wallet: string;
187
+ identity_status: "resolved" | "infrastructure" | "unavailable";
188
+ resolved_user_id?: string | null;
189
+ wallet_family?: string | null;
190
+ resolution_block?: number | null;
191
+ resolution_source?: string | null;
192
+ display_name?: string | null;
193
+ grade?: string | null;
194
+ /** 0xinsider profile path segment for this participant, present only when the execution wallet has a tracked trader: `@<username>` when that username resolves to the trader alone, otherwise the trader's lowercase wallet. Percent-encode the part after `@` and append to `https://0xinsider.com/profile/`. */
195
+ profile_segment?: string | null;
196
+ maker_fill_count: number;
197
+ /** Exact decimal shares. */
198
+ filled_shares: string;
199
+ /** Exact decimal USDC amount. */
200
+ filled_usdc: string;
201
+ /** Participant share of the exact execution, from 0 through 100. */
202
+ share_pct: string;
203
+ match_breakdown: CounterpartyMatchBreakdown[];
204
+ };
205
+ export type CreateWebhookRequest = {
206
+ name: string;
207
+ /** Public HTTPS callback URL on the default port 443. Local, private, and internal targets are rejected, as is any explicit port other than 443 and any URL carrying credentials. Each user's URLs are unique after normalizing HTTPS scheme/host case, trailing DNS dots and port 443; path/query case is preserved. Pending verification and PATCH-disabled endpoints still reserve their stored URL. The destination must answer the signed webhook.verification challenge with a 2xx before POST /api/v1/webhooks/{id}/verify can activate the endpoint. */
208
+ url: string;
209
+ event_types: WebhookEventType[];
210
+ };
211
+ export type EventReplayEvent = {
212
+ /** Opaque event ID; currently identical to cursor for the whale_alerts.id sequence. */
213
+ id: string;
214
+ type: "whale_trades_inserted";
215
+ /** Cursor positioned at this event. */
216
+ cursor: string;
217
+ /** Global whale_alerts.id sequence. */
218
+ sequence: number;
219
+ published_at: string;
220
+ payload: Record<string, unknown>;
221
+ source: EventReplaySource;
222
+ freshness: EventReplayFreshness;
223
+ };
224
+ export type EventReplayFreshness = {
225
+ status: "observed";
226
+ observed_at: string;
227
+ };
228
+ export type EventReplayMeta = {
229
+ /** Unique request ID (req_ prefix). */
230
+ request_id: string;
231
+ cached: boolean;
232
+ cache_age_s?: number | null;
233
+ /** Advisory request weight (relative compute cost). 1 for simple reads; higher for heavier endpoints. Not a credit/price. */
234
+ cost: number;
235
+ replay: {
236
+ from_cursor: string;
237
+ to_cursor: string;
238
+ from_sequence: number;
239
+ to_sequence: number;
240
+ ordering: "whale_alerts_id_asc";
241
+ };
242
+ retention: {
243
+ status: "durable_database";
244
+ retained_events: number;
245
+ cursor_expired: false;
246
+ };
247
+ completeness: {
248
+ status: "complete" | "caught_up";
249
+ reason: string;
250
+ };
251
+ };
252
+ export type EventReplaySource = {
253
+ kind: "local_durable_replay";
254
+ producer_family: "whale_trades";
255
+ owner: "whale_alerts";
256
+ provider_fetch_at_request_time: false;
257
+ };
258
+ export type ExploreEntry = ExploreGroup | ExploreStandalone;
259
+ export type ExploreFacets = {
260
+ categories: ExploreFacetValue[];
261
+ platforms: ExploreFacetValue[];
262
+ };
263
+ export type ExploreFacetValue = {
264
+ value: string;
265
+ label: string;
266
+ count: number;
267
+ };
268
+ export type ExploreGroup = {
269
+ type: "group";
270
+ event_slug: string;
271
+ parent_title: string;
272
+ image?: string | null;
273
+ platform?: string | null;
274
+ category?: string | null;
275
+ /** Markets in the event cluster, ranked by volume with condition_id as the tie-breaker. The selected representative is retained within the 12-market cap. */
276
+ markets: ExploreMarket[];
277
+ rep_volume?: number | null;
278
+ rep_whales?: number | null;
279
+ };
280
+ export type ExploreMarket = {
281
+ id: string;
282
+ condition_id: string;
283
+ /** Non-empty market title. */
284
+ title: string;
285
+ /** Provider-native market slug. */
286
+ slug?: string | null;
287
+ /** First-party market page slug used for internal links. */
288
+ url_slug?: string | null;
289
+ image?: string | null;
290
+ icon?: string | null;
291
+ category?: string | null;
292
+ platform?: string | null;
293
+ status: "active" | "closed";
294
+ volume?: number | null;
295
+ liquidity?: number | null;
296
+ whale_trade_count?: number | null;
297
+ whale_distinct_wallets?: number | null;
298
+ whale_total_usd?: number | null;
299
+ whale_last_trade_at?: string | null;
300
+ end_date?: string | null;
301
+ created_at?: string | null;
302
+ outcome_yes?: string | null;
303
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the YES outcome; null when unavailable (e.g. unsynced markets). */
304
+ token_id_yes?: string | null;
305
+ outcome_no?: string | null;
306
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the NO outcome; null when unavailable (e.g. unsynced markets). */
307
+ token_id_no?: string | null;
308
+ event_slug?: string | null;
309
+ smart_score?: number | null;
310
+ smart_count?: number | null;
311
+ smart_label?: string | null;
312
+ /** Display label for the YES/outcome_index=0 side, enriched from provider outcome metadata when available. */
313
+ outcome_yes_label?: string | null;
314
+ /** Display label for the NO/outcome_index=1 side, enriched from provider outcome metadata when available. */
315
+ outcome_no_label?: string | null;
316
+ /** Provider-owned YES/outcome_index=0 identifier when available for trade-ticket wiring. */
317
+ outcome_yes_provider_id?: number | null;
318
+ /** Provider-owned NO/outcome_index=1 identifier when available for trade-ticket wiring. */
319
+ outcome_no_provider_id?: number | null;
320
+ open_interest?: number | null;
321
+ oi_change_pct?: number | null;
322
+ price_points?: number[][] | null;
323
+ no_price_points?: number[][] | null;
324
+ last_price?: number | null;
325
+ no_last_price?: number | null;
326
+ change_pct_24h?: number | null;
327
+ no_change_pct_24h?: number | null;
328
+ /** Backend-owned deterministic market discovery score used by the hot sort. */
329
+ discover_score?: number | null;
330
+ score_components?: {
331
+ volume_signal?: number | null;
332
+ whale_signal?: number | null;
333
+ liquidity_signal?: number | null;
334
+ recency_signal?: number | null;
335
+ smart_money_signal?: number | null;
336
+ price_move_signal?: number | null;
337
+ missing_price_penalty: number;
338
+ };
339
+ freshness?: {
340
+ enrichment_status: "available" | "unavailable";
341
+ price_status: "available" | "unavailable";
342
+ };
343
+ };
344
+ export type ExploreStandalone = {
345
+ type: "standalone";
346
+ market: ExploreMarket;
347
+ };
348
+ export type ExportCompleteness = {
349
+ status: "complete" | "partial" | "empty";
350
+ reason: string;
351
+ sync_coverage: number;
352
+ };
353
+ export type ExportCounts = {
354
+ pnl_days: number;
355
+ exported_markets: number;
356
+ estimated_trade_rows: number;
357
+ estimated_size_mb: number;
358
+ };
359
+ export type ExportSourceRange = {
360
+ first_pnl_date?: string | null;
361
+ last_pnl_date?: string | null;
362
+ latest_trade_at?: string | null;
363
+ latest_market_activity_at?: string | null;
364
+ };
365
+ export type ExportVolumeReconciliation = {
366
+ provider_lifetime_volume?: number | null;
367
+ exported_activity_volume: number;
368
+ exported_market_cost_basis: number;
369
+ provider_activity_volume_gap?: number | null;
370
+ activity_volume_coverage?: number | null;
371
+ };
372
+ export type LargeExportPolicy = {
373
+ mode: "v1_async_export";
374
+ current_internal_route: string;
375
+ /** Programmatic API-key-gated export routes (submit/status/download) and supported formats (json, ndjson, csv). */
376
+ v1_async: {
377
+ /** POST route template to submit an export job. */
378
+ submit_route?: string;
379
+ /** GET route template to poll job status. */
380
+ status_route?: string;
381
+ /** GET route template that 302-redirects to the file. */
382
+ download_route?: string;
383
+ /** Supported ?format= values. */
384
+ formats?: ("json" | "ndjson" | "csv")[];
385
+ /** Possible job status values. */
386
+ status_values?: ("queued" | "running" | "ready" | "failed")[];
387
+ /** How long a finished export is retained before expiry. */
388
+ retention?: string;
389
+ };
390
+ direct_streaming: Record<string, unknown>;
391
+ async_job: Record<string, unknown>;
392
+ rate_limit: Record<string, unknown>;
393
+ };
394
+ export type LargePosition = {
395
+ /** Composite prefixed ID `pos_<wallet>:<condition_id>:<outcome_index>`. */
396
+ id: string;
397
+ /** Provider discriminator. Always polymarket. */
398
+ platform: "polymarket";
399
+ /** Aggregate provider currentValue for this position leg in USD. */
400
+ total_size_usd?: number | null;
401
+ /** Provider per-position unrealized P&L (trader_markets.unrealized_pnl_num, from Polymarket cashPnl). */
402
+ position_unrealized_pnl?: number | null;
403
+ /** Live share count for this position. */
404
+ share_count: number;
405
+ /** Volume-weighted entry price. */
406
+ avg_entry_price?: number | null;
407
+ /** Latest provider mark price for the position's token. */
408
+ current_price?: number | null;
409
+ /** Backend-resolved outcome label (provider outcome, else Yes/No from the binary index). */
410
+ outcome_label?: string | null;
411
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
412
+ token_id?: string | null;
413
+ /** Legs collapsed into this representative row for one (wallet, event, outcome side) group. 1 means standalone. */
414
+ event_leg_count: number;
415
+ /** Aggregate provider currentValue across collapsed sibling legs; equals total_size_usd when event_leg_count = 1. */
416
+ event_total_value_usd?: number | null;
417
+ first_seen_at: string;
418
+ last_updated_at: string;
419
+ trader: {
420
+ /** Prefixed ID (`trd_...`). */
421
+ id: string;
422
+ address: string;
423
+ username?: string | null;
424
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
425
+ win_rate?: number | null;
426
+ /** Trader lifetime realized P&L across all markets. */
427
+ pnl?: number | null;
428
+ markets_traded?: number | null;
429
+ };
430
+ market: {
431
+ /** Prefixed ID (`mkt_...`). */
432
+ id: string;
433
+ condition_id: string;
434
+ title?: string | null;
435
+ slug?: string | null;
436
+ event_slug?: string | null;
437
+ category?: string | null;
438
+ };
439
+ };
440
+ export type LeaderboardEntry = {
441
+ id: string;
442
+ address: string;
443
+ username?: string | null;
444
+ grade?: string | null;
445
+ /** Hot-streak tier (trailing-7d cross-sectional percentile); a separate axis from the all-time grade. Null when no recent activity. */
446
+ streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
447
+ score?: number | null;
448
+ /** All-time P&L in USD (total_pnl), including unrealized open positions. Kept for back-compat; prefer realized_pnl for the banked figure. */
449
+ pnl?: number | null;
450
+ /** All-time banked realized P&L in USD (total_pnl - open_pnl), excluding unrealized open positions. Matches the realized-P&L-dominant grade/board. */
451
+ realized_pnl?: number | null;
452
+ volume?: number | null;
453
+ markets_traded?: number | null;
454
+ win_rate?: number | null;
455
+ strategy_type?: string | null;
456
+ platform: string;
457
+ last_active?: string | null;
458
+ };
459
+ /** Provider-first bucketed OHLC price candles for a market's outcome tokens, derived from the stored token_price_snapshots series (covers open and resolved markets). */
460
+ export type MarketCandles = {
461
+ /** Market condition id the candles were read for. */
462
+ condition_id: string;
463
+ /** Bucketing granularity that produced these candles. */
464
+ resolution: "1d" | "1w";
465
+ /** One entry per present provider token (YES first, then NO); empty when no tokens have been fetched yet. */
466
+ outcomes: OutcomeCandles[];
467
+ };
468
+ export type MarketIntel = {
469
+ market: {
470
+ id: string;
471
+ condition_id: string;
472
+ title: string;
473
+ slug?: string | null;
474
+ category?: string | null;
475
+ platform?: string | null;
476
+ };
477
+ /** Outcome-aware flow from all tracked whale trades in the window, without a grade filter. BUY YES and SELL NO add net exposure; BUY NO and SELL YES subtract it. Gross buy/sell volumes count both outcomes. Top positions are separately graded. Direction uses unrounded net: negative is NO, otherwise YES; the zero tie-break is not conviction. Canonical; smart_money is a deprecated byte-identical alias. */
478
+ sharp_money: {
479
+ net_flow_usd: number;
480
+ direction: "YES" | "NO";
481
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
482
+ token_id?: string | null;
483
+ whale_trade_count: number;
484
+ buy_volume_usd: number;
485
+ sell_volume_usd: number;
486
+ top_positions: ({
487
+ id: string;
488
+ address: string;
489
+ username?: string | null;
490
+ grade?: string | null;
491
+ side: "YES" | "NO";
492
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
493
+ token_id?: string | null;
494
+ size_usd: number;
495
+ })[];
496
+ };
497
+ /** Deprecated alias of sharp_money; byte-identical and retained for backward compatibility. */
498
+ smart_money: {
499
+ net_flow_usd: number;
500
+ direction: "YES" | "NO";
501
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
502
+ token_id?: string | null;
503
+ whale_trade_count: number;
504
+ buy_volume_usd: number;
505
+ sell_volume_usd: number;
506
+ top_positions: ({
507
+ id: string;
508
+ address: string;
509
+ username?: string | null;
510
+ grade?: string | null;
511
+ side: "YES" | "NO";
512
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
513
+ token_id?: string | null;
514
+ size_usd: number;
515
+ })[];
516
+ };
517
+ timeframe: string;
518
+ };
519
+ export type MarketSearchResult = {
520
+ id: string;
521
+ condition_id: string;
522
+ title: string;
523
+ slug?: string | null;
524
+ category?: string | null;
525
+ platform?: string | null;
526
+ status: "active" | "closed";
527
+ };
528
+ export type MarketSnapshot = {
529
+ market: {
530
+ id: string;
531
+ condition_id: string;
532
+ provider: string;
533
+ title?: string | null;
534
+ slug?: string | null;
535
+ page_slug?: string | null;
536
+ event_slug?: string | null;
537
+ category?: string | null;
538
+ status: "active" | "closed";
539
+ description?: string | null;
540
+ image?: string | null;
541
+ /** Polymarket series slug from the canonical identity row, null when unavailable. A sports series identifies a league and must not be used as a per-matchup grouping key. */
542
+ series_slug?: string | null;
543
+ market_type?: string | null;
544
+ market_result?: string | null;
545
+ created_at?: string | null;
546
+ end_date?: string | null;
547
+ resolved_at?: string | null;
548
+ };
549
+ outcomes: ({
550
+ side: "yes" | "no";
551
+ label: string;
552
+ token_id?: string | null;
553
+ current_price?: number | null;
554
+ top_of_book: MarketSnapshotTopOfBook;
555
+ })[];
556
+ liquidity: {
557
+ source: string;
558
+ volume_usd?: number | null;
559
+ liquidity_usd?: number | null;
560
+ volume_24h_usd?: number | null;
561
+ /** Always null. Polymarket snapshot prices come from outcome top-of-book midpoints. */
562
+ last_price?: number | null;
563
+ };
564
+ sports: {
565
+ status: "fresh" | "stale" | "not_live" | "unavailable";
566
+ source: string;
567
+ live_match_key?: string | null;
568
+ live_league_key?: string | null;
569
+ /** Live-score period and elapsed may be omitted when unavailable (older responses use null). A score entry may omit full_name when it equals team; fall back to team. Distinct aliases and score admission markers are preserved. */
570
+ live_score?: Record<string, unknown> | null;
571
+ reason?: string | null;
572
+ };
573
+ freshness: {
574
+ market_data: MarketSnapshotFreshness;
575
+ top_of_book: MarketSnapshotFreshness;
576
+ /** Freshness requires the dedicated two-second post-publication marker to match the retained vintage and non-invalidated data timestamp; timestamp presence alone is insufficient. as_of records compute start, so stale_after_s is omitted rather than implying as_of plus two seconds. Missing membership is not_live only in a fresh source; stale membership remains stale and unreadable source data is unavailable. Repeated lookups reuse the shared payload and typed index for an unchanged generation. */
577
+ live_sports: MarketSnapshotFreshness;
578
+ };
579
+ /** Price and spread trust metadata. Present only when expand=trust or expand[]=trust is requested. */
580
+ trust?: MarketSnapshotTrust;
581
+ };
582
+ export type MarketSnapshotFreshness = {
583
+ status: "fresh" | "stale" | "available" | "not_live" | "unavailable";
584
+ source: string;
585
+ as_of?: string | null;
586
+ /** Age-relative freshness bound when known. Omitted for live_sports: its as_of records compute start, while its two-second freshness marker starts at publication. */
587
+ stale_after_s?: number | null;
588
+ reason?: string | null;
589
+ };
590
+ export type MarketSnapshotTopOfBook = {
591
+ status: "available" | "unavailable";
592
+ source: string;
593
+ best_bid?: number | null;
594
+ best_ask?: number | null;
595
+ spread_bps?: number | null;
596
+ bid_depth_usdc?: number | null;
597
+ ask_depth_usdc?: number | null;
598
+ reason?: string | null;
599
+ };
600
+ /** Price and spread trust metadata returned only when GET /api/v1/market/{condition_id}/snapshot includes expand=trust. */
601
+ export type MarketSnapshotTrust = {
602
+ current_price: TrustMetadata;
603
+ spread_bps: TrustMetadata;
604
+ };
605
+ export type McpJsonRpcError = {
606
+ jsonrpc: "2.0";
607
+ id?: string | number | null;
608
+ error: {
609
+ code: number;
610
+ message: string;
611
+ /** Optional JSON-serializable error data. */
612
+ data?: Record<string, unknown> | unknown[] | string | number | boolean | null;
613
+ };
614
+ };
615
+ /** One outcome token's bucketed candle series. */
616
+ export type OutcomeCandles = {
617
+ /** Provider CLOB token id the candles were read for. */
618
+ token_id: string;
619
+ /** Canonical side label. */
620
+ outcome: "YES" | "NO";
621
+ /** OHLC candles for this outcome token, ascending by bucket start. */
622
+ candles: Candle[];
623
+ };
624
+ export type PickHolder = {
625
+ address: string;
626
+ name?: string | null;
627
+ /** All-time trader grade (S, A, B, C, D, F). */
628
+ grade?: string | null;
629
+ /** 0xinsider profile path segment this wallet links to: `@<username>` when that username resolves to this wallet alone, otherwise the lowercase wallet. Percent-encode the part after `@` and append to `https://0xinsider.com/profile/`. Stamped at serve time; absent on a body cached before the field shipped. */
630
+ profile_segment?: string | null;
631
+ shares: number;
632
+ /** This wallet's win rate in the pick's canonical category bucket (the pick's `category` field, e.g. Basketball -- label the rate with it, never with the narrower `display_category` league): the share of the wallet's resolved markets in that category whose realized P&L closed positive, as a 0..1 fraction. Present only with `category_win_rate_status` = `measured`, on `display_holders` entries, and only when the wallet clears the resolved-market floor; recomputed at serve time from the current category read model, not frozen with the pick. Absent on `holders` entries, legacy rows, and payloads predating the field. */
633
+ category_win_rate?: number | null;
634
+ /** Why `category_win_rate` is present or absent on a `display_holders` entry: `measured` (rate present), `not_enough_data` (the wallet is below the resolved-market floor of 5 in the category), or `unavailable` (the annotation read failed; retry later). Absent entirely on `holders` entries, legacy rows, and payloads predating the field -- absence means the roster was never annotated, not a small sample. */
635
+ category_win_rate_status?: "measured" | "not_enough_data" | "unavailable";
636
+ };
637
+ export type PickOfTheDay = {
638
+ /** Always 'full' for an authenticated Pro key. */
639
+ state: "full";
640
+ /** The pick's local publication date (YYYY-MM-DD). */
641
+ pick_date: string;
642
+ /** Stable 1-based slot within the product day's ranked picks. */
643
+ pick_rank?: number;
644
+ /** The complete ranked picks for this product day, ordered by pick_rank. Thin days contain fewer items; the selector never fabricates rows. */
645
+ picks?: PickOfTheDay[];
646
+ /** Number of items in `picks`: the proof-readable picks. Picks held in `proof_pending_picks` are not counted. */
647
+ pick_count?: number;
648
+ /** Same-day picks selected but not yet released, ordered by pick_rank. Additive and optional: present only while at least one unreleased slot exists. Each slot exposes only its rank and schedule -- no market identity before release. Schedule the next read from the earliest release_at instead of polling. */
649
+ scheduled_picks?: ScheduledPickSlot[];
650
+ /** Human-readable matchup (e.g. "Portugal vs. Uzbekistan"). */
651
+ matchup: string;
652
+ /** Frozen canonical calibration/report bucket (e.g. "Basketball", "MMA", or "Soccer"). Existing semantics are unchanged; presentation consumers should prefer display_category when present. */
653
+ category: string;
654
+ /** Frozen public presentation category. For supported Polymarket sports this is the exact verified provider event identity: an official league (e.g. "WNBA" or "UFC"), the esports title (e.g. "CS2", "LoL", "Dota 2" or "Valorant"), or a soccer competition whose official mark we vendor (e.g. "LaLiga", "Premier League", "Serie A" or "UEFA Champions League"). Only identities with a vendored official mark are split out; every other competition keeps its canonical bucket, so "Soccer" remains a live value; otherwise it equals category. An esports pick keeps the pooled "Esports" bucket in category, so a per-title label never implies a per-title measured cohort. Additive and optional for mixed-version client compatibility. */
655
+ display_category?: string;
656
+ /** Provider platform (e.g. "polymarket"). */
657
+ platform: string;
658
+ /** The pick's stored release instant. Normally the current provider kickoff minus one hour; an operator may override it. The actual publish instant can trail it because of worker or claim delay. */
659
+ release_at: string;
660
+ /** True only before the pick's stored release instant (a pre-release embargo flag); effectively always false on a served, already-published pick. To detect that the backed game has kicked off, use `game_started`. */
661
+ is_locked: boolean;
662
+ /** True once the backed game's kickoff has passed (kickoff <= now). When true the snapshotted pre-game price is no longer actionable. Absent for a legacy pick with no stored kickoff (treat as not-started). */
663
+ game_started?: boolean;
664
+ /** Settlement outcome of the backed side; 'pending' until the market resolves. */
665
+ outcome: "pending" | "win" | "loss" | "void";
666
+ /** Pre-formatted SETTLEMENT STATUS for display: "Win" / "Loss" / "Void" / "Pending" -- the outcome enum above as a label. Convenience only; outcome is the source value. NOTE: this is the win/loss STATUS, not the backed side. The backed side is pick_outcome_label ("Belgium (-2.5)") -- a different field answering a different question. */
667
+ outcome_display?: string;
668
+ /** The backed side phrased as a bet: a team for a moneyline (e.g. "Portugal"), the handicap line for a spread (e.g. "Belgium (-2.5)"), or "{team} to advance" for a knockout advancement market (e.g. "Spain to advance"). */
669
+ pick_outcome_label: string;
670
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the backed outcome; null when unavailable (e.g. unsynced markets). */
671
+ token_id?: string | null;
672
+ /** The backed side phrased as a bet (e.g. "Portugal to win"). */
673
+ position: string;
674
+ /** One-line summary of which side sharp money is backing. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof. */
675
+ side_summary: string;
676
+ /** Public V1 compatibility count of S/A smart-money wallets on the backed side. The first-party/internal current policy counts S/A/B; historical rows retain their frozen policy's count. Required on every item in `picks`: a current-day published pick whose required holder proof is not safely readable is listed in `proof_pending_picks` instead of being served with a partial success shape or a synthetic zero, and the route returns 503 read_model_warming only when no published pick has readable proof. */
677
+ smart_wallet_count: number;
678
+ /** Best public V1-compatible S/A smart-money grade on the backed side. The first-party/internal current policy can select B, but a current B-only grade is omitted by the stable V1 adapter. Historical rows retain their frozen policy's grade. A current-day published pick with pending legacy proof, unknown-future proof, or structurally invalid current-policy proof returns 503 before this success schema is served. Resolved legacy proof remains readable on both current-day and archive/history responses. */
679
+ top_grade?: string | null;
680
+ /** Deprecated (#7170): no longer populated for picks selected on/after the calibration-edge change; omitted (absent) for new picks (the field uses skip_serializing_if, so a null value is dropped from the JSON rather than serialized as null). Permanently frozen-legacy -- retained for historical picks, with no removal or replacement planned, so no v2 is implied. Historical picks may still carry a value. Legacy meaning: category win-rate edge as a fraction (the backed-side cohort's win rate in this category minus the non-market-maker category baseline, e.g. 0.09 = +9 points), paired with category_edge_sample. */
681
+ category_edge_pct?: number | null;
682
+ /** Deprecated (#7170): no longer populated for picks selected on/after the calibration-edge change; omitted (absent) for new picks (the field uses skip_serializing_if, so a null value is dropped from the JSON rather than serialized as null). Permanently frozen-legacy -- retained for historical picks, with no removal or replacement planned, so no v2 is implied. Historical picks may still carry a value. Legacy meaning: pooled count of resolved markets behind category_edge_pct (the headline's n). */
683
+ category_edge_sample?: number | null;
684
+ /** Recency-weighted graded-flow magnitude in USD; omitted when <= 0. */
685
+ smart_usd?: number | null;
686
+ /** Pre-game snapshot probability (0..1) for the backed side. */
687
+ backed_price?: number | null;
688
+ /** Full-only disclosure when backed_price was recovered from provider history within 30 seconds before publication. Render beside the price. Absent for ordinary publication captures and teasers; this is a historical reference, not an executed fill. */
689
+ entry_price_note?: string;
690
+ /** Pre-formatted backed_price as cents-on-the-dollar odds, to ONE decimal: "62.0c" / "99.9c". Never rounded to a whole cent -- a 99.9c favorite is not a 100c certainty. Convenience only; backed_price is the source value. Omitted when backed_price is. */
691
+ odds_display?: string | null;
692
+ /** Gross return on a $100 stake at the snapshotted price (100 / backed_price). */
693
+ return_per_100?: number | null;
694
+ /** Pre-formatted return_per_100 as USD with cents and thousands separators: "$161.29" / "$1,250.00". The GROSS return (the $100 stake included), so it carries no sign. Convenience only; return_per_100 is the source value. Omitted when return_per_100 is. */
695
+ payout_display?: string | null;
696
+ /** Pre-formatted PROFIT on the $100 stake -- return_per_100 minus the 100 stake, i.e. the payout net of what you put in -- as a signed USD string: "+$61.29". Distinct from payout_display, which is gross. Omitted when return_per_100 is. */
697
+ profit_display?: string | null;
698
+ /** Backend-owned CLV capture disposition. "pending" means no capture decision exists yet; terminal provider or quality statuses remain distinguishable. The raw close price and timestamp are never serialized. */
699
+ clv_status: string;
700
+ /** Backend-owned CLV evidence basis. `frozen_displayed_entry` uses the persisted displayed entry. `historical_provider_entry` uses a known-CLOB point at or before publication. `historical_provider_price_match` requires the latest point in the prior hour to match. `historical_provider_nearby_price_match` requires a matching point within five minutes before publication. Source-null bases preserve unknown original provenance. */
701
+ clv_basis?: string;
702
+ /** Closing-line value toward the backed side, computed as (close / entry - 1) * 100. The basis-specific provider p entry must match the stored display; historical_provider_price_match also requires source provenance to remain null and its latest entry to be within the one-hour window at or before publication. Every basis requires a later quality-checked p close from the same series in the bounded post-entry, pre-kickoff window. Omitted when not measured. */
703
+ clv_pct?: number;
704
+ /** Backend-formatted signed CLV percentage, present exactly when clv_pct is present. */
705
+ clv_display?: string;
706
+ /** Backend-owned CLV formula text with the entry probability, close probability, and rounded result. Provider timestamps remain private. */
707
+ clv_explanation?: string;
708
+ /** Net return for the pick in the existing $100 stake units. Omitted when the outcome is not valued. */
709
+ unit_score?: number;
710
+ /** Backend-formatted signed unit score, present exactly when unit_score is present. */
711
+ unit_score_display?: string;
712
+ /** First-party/internal backed-side sharp-money dollar consensus as a fraction 0..1: the share of current-policy sharp dollars on the backed side. Omitted on current public V1 rows when the B-inclusive value has no reconstructible S/A equivalent. A conviction signal, NOT a probability or expected-value claim. Frozen at generation. */
713
+ sharp_pct?: number | null;
714
+ /** Market-implied probability of the backed side as a fraction 0..1 (equals backed_price), re-exposed alongside sharp_pct for the WHY breakdown. */
715
+ market_pct?: number | null;
716
+ /** First-party/internal consensus edge = sharp_pct - market_pct, the conviction-vs-price gap (how much more of the current-policy sharp money sits on this side than the price implies). Omitted on current public V1 rows when the B-inclusive value has no reconstructible S/A equivalent. This is NOT an expected-value or guaranteed edge. Null when either input is null. */
717
+ consensus_edge_pct?: number | null;
718
+ /** First-party/internal team-directional commitment read at selection time: the fraction (0..1) of the backed side's current-policy graded sharp-money DOLLARS held by wallets read one-way rather than hedged: no opposite leg on this market worth at least 10% of the backed leg (Polymarket's own currentValue pair), and no opposing team across the game's markets where the wallet's synced legs are fresh. Current public V1 rows omit this B-inclusive read because its historical S/A equivalent is not reconstructed. A high value means the graded pile is really committed to this side; a low one means much of it is hedged or unreadable. Omitted when the read was not computed (a pick selected before the field existed, an ungroupable game, an empty graded pile, or a pile where no holder carried usable evidence) -- which is NOT the same as 0.0, a computed reading that classified holders and found none one-way. */
719
+ directional_confidence?: number | null;
720
+ /** Graded backed-side holders read as one-way-committed on this game. */
721
+ one_way_holder_count?: number | null;
722
+ /** Graded backed-side holders read as HEDGED across the game's markets. */
723
+ hedged_holder_count?: number | null;
724
+ /** The one-way holders' share of the backed-side graded dollars (the confidence's numerator). */
725
+ one_way_graded_usd?: number | null;
726
+ /** Backed-side graded dollars the confidence is measured against (its denominator). */
727
+ total_graded_usd?: number | null;
728
+ /** The qualifying category expert whose sport-specific record and real position earned this pick its top selection tier. The first-party/internal current policy admits S/A/B; public V1 exposes a compatible S/A expert and omits a current-policy B-grade expert: a candidate backed by one outranks every candidate without one. Present only on the full payload. Omitted when no wallet qualified on the backed side, on picks generated before the field existed, and on the first-party web teaser, which withholds all backed-side evidence. Frozen at SELECTION time — the wallet's position can move before the pick renders. */
729
+ qualifying_expert?: {
730
+ /** Wallet address of the qualifying expert. */
731
+ address: string;
732
+ /** Provider display name, or null for an unnamed wallet. */
733
+ name?: string | null;
734
+ /** 0xinsider grade letter. The first-party/internal current Pick of the Day policy counts S, A, and B; public V1 exposes only the compatible S/A expert. */
735
+ grade?: string | null;
736
+ /** The canonical sport bucket the win rate was measured over (for example Basketball). Can be BROADER than the pick's display_category, which names an exact league such as NBA — label the rate with this field, never with display_category. */
737
+ canonical_category: string;
738
+ /** Share of this wallet's resolved markets in canonical_category whose realized P&L came out positive, as a 0..1 fraction. Above 0.60 by construction for a source=v1 expert; null for an expert who qualified on the category-skill v2 definition only. Deliberately NOT phrased as "closed profitable": the metric counts realized P&L above zero, so a resolved winner the wallet never redeemed sits at zero and counts against it. */
739
+ win_rate?: number | null;
740
+ /** Resolved markets in canonical_category behind win_rate. At least 10 by construction for a source=v1 expert; null with win_rate. */
741
+ n_resolved?: number | null;
742
+ /** Current expert policy 10 does not require a category-skill v2 specialist in any sport; in every sport a specialist raises the candidate's rank tier rather than gating it. Standard specialists need a positive edge_lower_95 over enough independent events and enough net backing on the backed side; the floors are not published. Fresh healthy records below the shared model's live sample floor can qualify; stale, unknown and degraded records cannot. Historical records preserve which definition qualified the wallet: v1, the profitability rate (win_rate over n_resolved), or v2, the forward-only category-skill calibration edge (edge_lower_95 over independent_event_count). Absent on picks frozen before the v2 definition existed; read absence as v1. A Tennis pick frozen under gate policy v4 or later carries v2 only: a v1 rate stopped qualifying a tennis expert at v4. A Tennis pick frozen under an earlier policy can still carry v1 with a win rate. */
743
+ source?: "v1" | "v2";
744
+ /** 95% lower bound of the wallet's mean calibration edge over the market price in canonical_category, in probability units (0.08 is 8 points). Positive by construction for a v2 expert; present on a v1 expert only when the wallet also holds a live v2 row. */
745
+ edge_lower_95?: number | null;
746
+ /** Point estimate behind edge_lower_95. */
747
+ edge_mean?: number | null;
748
+ /** Independent canonical events behind the edge. At least 10 by construction for a v2 expert. */
749
+ independent_event_count?: number | null;
750
+ /** Polymarket's own currentValue for this wallet on the backed outcome, in USD, as of selection. At least 1000 by construction through gate policy v7; the standard floor is 500 from v8. From gate policy v5 the floor is read on the net: position_usd minus opposite_position_usd is at least that floor, and the pick re-verifies that net against the live holder snapshot when it is released. */
751
+ position_usd: number;
752
+ /** The same wallet's currentValue on the OTHER outcome of this market, in USD, as of selection. Present from gate policy v5, when the floor moved to net exposure; a wallet long both sides does not qualify. Absent on picks frozen before v5, which never read the leg. 0 is a measured one-way position, not an absence. */
753
+ opposite_position_usd?: number | null;
754
+ /** When the skill read model behind the evidence was last rebuilt: trader_category_stats.computed_at for a source=v1 expert, category_skill_v2_current.as_of for a source=v2 expert. */
755
+ stats_computed_at: string;
756
+ /** Present from expert policy 6. Current expert policy 10 retains the longshot requirement of live v2 only, with a positive lower bound over a large sample, large net backed value and no meaningful opposite value. Historical policy 6: a specialist required large net backed value, no meaningful opposite value, and either a live v2 positive lower bound over a large sample or a high v1 rate over enough resolved markets. Tennis requires v2. The floors are not published. */
757
+ lane?: "standard" | "longshot_specialist";
758
+ /** Answered, spread-gated, index-scoped backed probability frozen only on a specialist exception. */
759
+ lane_probability?: number;
760
+ /** Canonical provider probability pair branch; absent on standard experts. */
761
+ lane_probability_source?: "p";
762
+ } | null;
763
+ trust?: PickTrust;
764
+ /** Public V1 S/A compatibility count on the backed side (equals the adapted smart_wallet_count). The first-party/internal current policy counts S/A/B. Historical rows retain their frozen policy's count. */
765
+ traders?: number | null;
766
+ /** Raw backed-side sharp-money USD frozen at generation. This is the Sharp USD value, not the recency-weighted smart_usd which decays. Omitted on current public V1 rows when the B-inclusive value has no reconstructible S/A equivalent. */
767
+ backed_sharp_usd?: number | null;
768
+ /** Bounded S/A compatibility projection of the frozen sharp-money holders on the backed side. Current full payloads expose the complete S/A/B roster in display_holders; historical rows can retain their earlier frozen shape. */
769
+ holders?: PickHolder[] | null;
770
+ /** Full-only complete provider-confirmed S/A/B holder roster for the current Pick of the Day backing policy. Omitted for teaser, no-pick, and historical rows whose frozen holder proof predates this policy. Each entry may additionally carry `category_win_rate` / `category_win_rate_status`: the wallet's win rate in the pick's canonical `category`, stamped at serve time from the current category read model (the same annotation the sports sharp-money chips carry). The bounded `holders` compatibility projection never carries these fields. */
771
+ display_holders?: PickHolder[] | null;
772
+ /** Exact S/A smart-money proof count on the backed side. The current display_holders roster can be longer because it also carries B-grade smart-money holders. */
773
+ holder_count?: number | null;
774
+ /** Optional editorial note attached to the pick. */
775
+ editorial_note?: string | null;
776
+ /** Required truthful thesis. With at least one profitable-wallet holder: Profitable wallets hold {pick_outcome_label}[, led by a grade-{top_grade} trader]. Without holder backing: 0xInsider's Pick of the Day is {pick_outcome_label}. Wallet counts are not appended. */
777
+ thesis: string;
778
+ /** Canonical web market URL. */
779
+ market_url?: string | null;
780
+ /** The canonical /event game-page slug (one neutral page per game), null when the game has no neutral event page. */
781
+ event_slug?: string | null;
782
+ /** Backend-resolved /event destination slug for this pick's source market; null is an authoritative no-link decision. */
783
+ event_link_slug?: string | null;
784
+ /** Provider-first sports context for the pick's market (team logos, league branding, live score). Full-state only; omitted when the pick is not a team-sports market. */
785
+ sports_context?: PickSportsContext;
786
+ /** Risk disclaimer shown with every pick. */
787
+ disclaimer: string;
788
+ /** Published same-day picks whose holder proof is not readable yet, ordered by pick_rank. Additive and optional: present only while at least one such pick exists. While present, `picks` carries only the proof-readable picks and `pick_count` counts them. Schedule the next read from the earliest retry_at instead of polling. The route returns 503 read_model_warming only when no published pick has readable proof. */
789
+ proof_pending_picks?: ProofPendingPickSlot[];
790
+ /** Frozen admission classification, full payload only. The specialist lane exempts two probability rejects and adds no rank bonus. Historical rows remain standard. */
791
+ selection_lane?: "standard" | "longshot_specialist";
792
+ /** Optional full-only authorization for newly issued policy-7 picks; omitted for legacy or unissued picks and teasers. It remains historical after expiry. */
793
+ entry_authorization?: PotdEntryAuthorization;
794
+ };
795
+ export type PickOfTheDayArchive = {
796
+ /** Every published Pick of the Day, newest first by pick_date and then pick_rank within each product day. */
797
+ picks: PickOfTheDayArchiveEntry[];
798
+ /** One entry per product day that has a published pick, 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. */
799
+ days: PickOfTheDayArchiveDay[];
800
+ hit_rate: PickOfTheDayHitRate;
801
+ };
802
+ export type PickOfTheDayArchiveDay = {
803
+ /** The product day (YYYY-MM-DD). */
804
+ date: string;
805
+ /** Published picks on the day: wins + losses + void + pending. */
806
+ picks: number;
807
+ /** Picks on the day that resolved as a win, counted by the same pass as hit_rate.wins, so the day entries sum to the headline record. */
808
+ wins: number;
809
+ /** Picks on the day that resolved as a loss, counted by the same pass as hit_rate.losses. */
810
+ losses: number;
811
+ /** Picks on the day that resolved void (stake refunded). */
812
+ void: number;
813
+ /** Picks on the day not yet resolved. A day whose picks are all pending is a real 0-0 day with pending > 0, not a missing record. */
814
+ pending: number;
815
+ /** Net units over the day's visible, valued, decided (win/loss) picks: the same population staked_usd runs over. Omitted when the day has not scored -- every pick still pending, every pick void, or a price-gated current row -- which is not the same as a real 0.0 day. */
816
+ unit_score?: number;
817
+ /** unit_score pre-formatted as signed units to two decimals (for example +1.24u or -2.00u), by the same formatter the per-pick unit_score_display and hit_rate.unit_score_display use. Present exactly when unit_score is; unit_score is the source value. */
818
+ unit_score_display?: string;
819
+ /** win when every decided pick on the day won, loss when every one lost, over at least three decided (win or loss) picks with nothing pending. Omitted for every other day. A void is not a result: it neither lifts a day over the floor nor spoils a sweep. */
820
+ sweep?: "win" | "loss";
821
+ };
822
+ export type PickOfTheDayArchiveEntry = {
823
+ /** The pick's local publication date (YYYY-MM-DD). */
824
+ pick_date: string;
825
+ /** Stable 1-based slot within the product day's ranked picks. */
826
+ pick_rank?: number;
827
+ /** Human-readable matchup (e.g. "Portugal vs. Uzbekistan"). */
828
+ matchup: string;
829
+ /** Frozen canonical calibration/report bucket (e.g. "Basketball", "MMA", or "Soccer"). Existing semantics are unchanged; presentation consumers should prefer display_category when present. */
830
+ category: string;
831
+ /** Frozen public presentation category. For supported Polymarket sports this is the exact verified provider event identity: an official league (e.g. "WNBA" or "UFC"), the esports title (e.g. "CS2", "LoL", "Dota 2" or "Valorant"), or a soccer competition whose official mark we vendor (e.g. "LaLiga", "Premier League", "Serie A" or "UEFA Champions League"). Only identities with a vendored official mark are split out; every other competition keeps its canonical bucket, so "Soccer" remains a live value; otherwise it equals category. An esports pick keeps the pooled "Esports" bucket in category, so a per-title label never implies a per-title measured cohort. Additive and optional for mixed-version client compatibility. */
832
+ display_category?: string;
833
+ /** Provider (Polymarket Gamma) market thumbnail URL (markets.image); omitted (not null) when the market has no image. Public regardless of the backed-side gate, so present for pending rows too. */
834
+ image_url?: string;
835
+ /** The backed side's outcome label. Omitted for a still-pending pick when the request is not from an authenticated Pro key. */
836
+ pick_outcome_label?: string | null;
837
+ /** Best public V1-compatible S/A smart-money grade on the backed side; a current B-only grade is omitted by the stable V1 adapter, while historical rows retain their frozen policy's grade. null when no smart-money wallet backs the pick, when a pending legacy proof has not yet upgraded, or when the stored holder policy is unknown-future or structurally invalid. Resolved legacy history remains supported. */
838
+ top_grade?: string | null;
839
+ /** Settlement outcome of the backed side; 'pending' until the market resolves. */
840
+ outcome: "pending" | "win" | "loss" | "void";
841
+ /** Pre-formatted settlement status for display: "Win" / "Loss" / "Void" / "Pending" -- the outcome enum above as a label, from the same formatter the pick payload's outcome_display uses. Convenience only; outcome is the source value. */
842
+ outcome_display?: string;
843
+ /** Gross return on a $100 stake on this resolved pick: a win returns 100 / backed_price, a loss returns 0, a void refunds 100. A loss always returns 0 (the whole stake is lost regardless of price). Omitted (not null) only for a still-pending pick or a resolved WIN with no frozen price (a win's payout needs the price); mirrors the backend skip-when-absent behavior and the route-client optional (non-nullable) schema. */
844
+ return_per_100?: number;
845
+ /** Pre-formatted return_per_100 as USD with cents: "$200.00". Present exactly when return_per_100 is -- it is formatted from that already-gated value -- so it is omitted for a still-pending pick, an unpriced win, and any pick whose backed side is withheld. Convenience only; return_per_100 is the source value. */
846
+ payout_display?: string;
847
+ /** Closing-line value toward the backed side, computed as (close / entry - 1) * 100. Omitted when the row is gated, ineligible, or not measured. */
848
+ clv_pct?: number;
849
+ /** Backend-formatted signed CLV percentage, present exactly when clv_pct is present. */
850
+ clv_display?: string;
851
+ /** Whether CLV applies. A visible resolved pick published after kickoff is not_applicable. */
852
+ clv_applicability?: "applicable" | "not_applicable";
853
+ /** Backend-owned CLV formula text or the reason that CLV does not apply or is unavailable. */
854
+ clv_explanation?: string;
855
+ /** Exact backend CLV capture disposition for this visible row. Pending and terminal provider or quality statuses are distinguishable; raw close evidence is never serialized. */
856
+ clv_status: string;
857
+ /** Backend-owned CLV evidence basis. Source-null price-match bases preserve unknown original provenance. `historical_provider_nearby_price_match` requires a matching Polymarket point within five minutes before publication. */
858
+ clv_basis?: string;
859
+ /** Net return for this pick in stake units, where one unit is the existing $100 stake. Omitted when the backed side is withheld or the pick is not valued. */
860
+ unit_score?: number;
861
+ /** Backend-formatted signed unit score, present exactly when unit_score is present. */
862
+ unit_score_display?: string;
863
+ };
864
+ export type PickOfTheDayHitRate = {
865
+ /** Number of decided picks that won. */
866
+ wins: number;
867
+ /** Number of decided picks that lost. */
868
+ losses: number;
869
+ /** Number of decided picks (wins + losses); excludes void and pending. */
870
+ decided: number;
871
+ /** Rolling hit rate as a percentage (wins / decided * 100, to 1 decimal); 0 when none are decided. */
872
+ pct: number;
873
+ /** Number of picks that resolved void (excluded from the hit rate). */
874
+ void: number;
875
+ /** Number of picks still pending resolution (excluded from the hit rate). */
876
+ pending: number;
877
+ /** Cumulative profit (USD) of a $100/pick strategy over visible valued decided picks: a priced win pays 100/backed_price - 100, every visible loss pays -100 independent of price, and a void pays 0. An unpriced visible win and a current non-Insider row whose price is gated remain in wins/losses but are excluded from price-derived totals. */
878
+ net_profit_usd: number;
879
+ /** Total staked (USD) = 100 * count of visible valued decided picks: every visible loss plus every priced win. Void, unpriced wins, and current non-Insider rows whose price is gated are excluded. */
880
+ staked_usd: number;
881
+ /** Return on the staked amount as a percentage (net_profit_usd / staked_usd * 100, to 1 decimal); 0 when nothing is staked. */
882
+ roi_pct: number;
883
+ /** Pre-formatted net profit for display, e.g. "+$100" / "-$40". Whole dollars, signed, round-then-signed so a rounds-to-zero record reads "+$0" (never "-$0"). Convenience only; net_profit_usd is the source value. */
884
+ net_profit_display: string;
885
+ /** Pre-formatted ROI for display, e.g. "+8.3%" / "-20.0%". One decimal, signed, round-then-signed so a rounds-to-zero record reads "+0.0%" (never "-0.0%"). Convenience only; roi_pct is the source value. */
886
+ roi_display: string;
887
+ /** Pre-formatted win rate for display, e.g. "92.3%". One decimal, unsigned. Convenience only; pct is the source value. */
888
+ win_rate_display: string;
889
+ /** Cumulative net return in stake units over the same valued win/loss population as net_profit_usd. */
890
+ unit_score?: number;
891
+ /** Backend-formatted signed cumulative unit score, for example "+1.25u". Omitted when no valued settled pick contributes to the aggregate. */
892
+ unit_score_display?: string;
893
+ /** Visible resolved archive rows with no CLV capture disposition yet. */
894
+ clv_pending: number;
895
+ /** Visible resolved archive rows with a terminal non-measured CLV disposition. */
896
+ clv_unavailable: number;
897
+ /** Aggregate CLV state. Counts remain available for mixed measured/pending/unavailable populations. */
898
+ clv_state: "measured" | "pending" | "unavailable" | "not_applicable" | "none";
899
+ /** Visible resolved archive rows with valid basis-specific CLV entry evidence. Known-source bases require CLOB provenance; historical_provider_price_match instead requires source provenance to remain null and the latest provider p entry in the one-hour window at or before publication to match the stored display. */
900
+ clv_eligible: number;
901
+ /** Every visible resolved archive row, including post-kickoff picks. A price-gated current row is excluded until its backed side becomes visible. */
902
+ clv_total: number;
903
+ /** Eligible resolved public rows with a measured Polymarket CLOB close. */
904
+ clv_measured: number;
905
+ /** Visible resolved rows published before kickoff. This is the CLV coverage denominator. */
906
+ clv_applicable: number;
907
+ /** Visible resolved rows published after kickoff. These rows remain public but do not enter coverage. */
908
+ clv_not_applicable: number;
909
+ /** Measured divided by clv_applicable as a percentage. Omitted when clv_applicable is zero. */
910
+ clv_coverage_pct?: number;
911
+ /** Backend-formatted measured/clv_applicable coverage percentage. */
912
+ clv_coverage_display?: string;
913
+ /** Backend-owned coverage count text, including the excluded post-kickoff count. */
914
+ clv_coverage_explanation?: string;
915
+ /** Arithmetic mean of per-pick ratio CLV, (close / entry - 1) * 100. A cheap entry weighs more here than a favorite, so the headline average is clv_avg_pp; this field is kept for continuity. Suppressed until at least five measured rows exist. */
916
+ clv_avg_pct?: number;
917
+ /** Backend-formatted signed average CLV percentage, present when clv_avg_pct is present. */
918
+ clv_avg_display?: string;
919
+ /** Arithmetic mean of the measured closing-line move in percentage points, (close - entry) * 100, so every pick counts on the same scale. The headline CLV average. Covers the same measured rows as clv_avg_pct and is suppressed under the same five-row floor. */
920
+ clv_avg_pp?: number;
921
+ /** Backend-formatted signed average in percentage points, for example "+0.4 pp"; a value that rounds to zero reads "0.0 pp". Present when clv_avg_pp is present. */
922
+ clv_avg_pp_display?: string;
923
+ /** Measured public rows where close is strictly greater than entry. */
924
+ clv_beats_close: number;
925
+ /** Measured public rows where close exactly equals entry. */
926
+ clv_ties: number;
927
+ /** Cumulative track-record series, one point per decided (win/loss) pick in ascending pick_date order (void and pending add no point). A non-valued decided row carries cumulative profit forward while advancing hit rate. The last point's net_profit_usd and hit_rate_pct equal the headline net_profit_usd and pct by construction. Empty when nothing is decided. */
928
+ series?: {
929
+ /** The decided pick's publish date (YYYY-MM-DD). */
930
+ date: string;
931
+ /** Running cumulative $100/pick profit (USD) through this pick; valued losses and priced wins are booked, while a non-valued decided row carries profit forward unchanged. */
932
+ net_profit_usd: number;
933
+ /** Running rolling hit rate (wins / decided * 100, to 1 decimal) through this pick. */
934
+ hit_rate_pct: number;
935
+ }[];
936
+ };
937
+ /** Provider-first sports context for a Pick of the Day market: team crests, league branding, and live score. Team logos and league logo are provider-owned (Polymarket /teams crests for clubs, country flags for national teams and tennis players); no local derivation. */
938
+ export type PickSportsContext = {
939
+ /** League or competition display name (e.g. "Premier League"). */
940
+ league_name?: string | null;
941
+ /** Provider-owned event taxonomy from Gamma eventMetadata, joined in league · serie · tournament order with blanks and case-insensitive duplicates removed. Separate from league_name; omitted when the provider does not supply the metadata. */
942
+ competition_label?: string | null;
943
+ /** League logo URL (provider-owned). */
944
+ league_logo?: string | null;
945
+ /** The team mapped to the market's YES outcome, or the parent-event home/first team when event_matchup is true. */
946
+ yes_team?: PickSportsTeam;
947
+ /** The team mapped to the market's NO outcome, or the parent-event away/second team when event_matchup is true. */
948
+ no_team?: PickSportsTeam;
949
+ /** Provider game identifier (Polymarket Gamma gameId); omitted when null. */
950
+ game_id?: number | null;
951
+ /** 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. */
952
+ event_matchup: boolean;
953
+ /** 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). */
954
+ event_subject_team?: PickSportsTeam;
955
+ /** 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. */
956
+ matchup_title?: string | null;
957
+ };
958
+ /** 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`, `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. */
959
+ export type PickSportsTeam = {
960
+ /** Team display label as it appears on the market outcome (e.g. "Portugal"). */
961
+ label?: string | null;
962
+ /** Abbreviated team label (e.g. "POR"). */
963
+ short_label?: string | null;
964
+ /** Full team or competitor name (e.g. "Portugal national football team"). */
965
+ full_name?: string | null;
966
+ /** Provider team identifier (Polymarket /teams id). */
967
+ provider_id?: number | null;
968
+ /** Team crest or flag URL. Provider-owned for most teams (Polymarket /teams crest for clubs, country flag for national teams and tennis players). A club with a vendored crest carries it instead, served same-origin as a relative path (`/api/sports/team-logos/{league}/{abbr}.svg?v=<content hash>` or `.png`, resolve it against this server): every NFL and WNBA team, whose provider asset is a text tile, and the soccer clubs whose provider asset is an empty object. */
969
+ logo?: string | null;
970
+ /** Team brand color as a hex string (provider-owned). */
971
+ color?: string | null;
972
+ /** Win-loss record as a display string (e.g. "12-4"). */
973
+ record?: string | null;
974
+ /** Live or final score as a display string when the game is in play or settled. */
975
+ score?: string | null;
976
+ /** 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. */
977
+ headshot?: string | null;
978
+ /** 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. */
979
+ tour?: "atp" | "wta" | "itf";
980
+ /** 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. */
981
+ sets?: ScoreCell[];
982
+ format?: ScoreFormat;
983
+ /** 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. */
984
+ sets_won?: number | null;
985
+ };
986
+ /** Field-level trust metadata for the full Pick of the Day payload. Present on the full shape only (omitted on the teaser and the no-pick state, because whether a specialist backs the pick is itself backed-side evidence). Unlike TraderTrust it is not gated behind expand=trust: it carries one member on an endpoint that returns a single object per day. */
987
+ export type PickTrust = {
988
+ /** Provenance of the frozen qualifying category expert. source.kind=database with reconciliation.status=db_mirror means the evidence deserialized, still satisfies every frozen selection gate, and is being served. On that arm freshness.status is always not_live and never fresh, because this evidence is frozen at selection and never refreshed, so on an archived pick the as_of (the expert's own stats_computed_at) can be days or months old by design. source.kind=computed with reconciliation.status=not_applicable means the selector evaluated the backed side and nobody qualified -- a real negative. source.kind=computed with freshness.status=unknown and completeness.status=not_computed means the selector never evaluated this field, as on a pre-feature pick or manual takeover. source.kind=unavailable means the payload is malformed, violates a selection gate, or conflicts with its persisted status, or the public V1 adapter intentionally omitted a current-policy B-grade expert; read the reason before treating it as a negative. Do not read an omitted qualifying_expert as 'no specialist' without checking this field. */
989
+ qualifying_expert: TrustMetadata;
990
+ };
991
+ export type PlatformCapabilities = {
992
+ grade: PlatformCapabilityStatus;
993
+ pnl: PlatformCapabilityStatus;
994
+ strategy: PlatformCapabilityStatus;
995
+ timeline: PlatformCapabilityStatus;
996
+ whale_signal: PlatformCapabilityStatus;
997
+ insider_radar: PlatformCapabilityStatus;
998
+ market_snapshot: PlatformCapabilityStatus;
999
+ };
1000
+ export type PlatformCapabilityStatus = "supported" | "partial" | "unsupported";
1001
+ export type Platforms = {
1002
+ platforms: {
1003
+ polymarket: PlatformCapabilities;
1004
+ };
1005
+ };
1006
+ export type Position = {
1007
+ /** Composite prefixed ID `pos_<wallet>:<condition_id>:<outcome_index>`. */
1008
+ id: string;
1009
+ /** Provider discriminator. Polymarket only. */
1010
+ platform: "polymarket";
1011
+ /** Lowercased proxy wallet address. */
1012
+ wallet: string;
1013
+ /** Binary outcome side. Non-binary positions are not surfaced on V1. */
1014
+ side: "YES" | "NO";
1015
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
1016
+ token_id?: string | null;
1017
+ /** Live share count from the wallet_positions mirror. */
1018
+ shares: number;
1019
+ /** Volume-weighted entry price for this leg. */
1020
+ avg_price?: number | null;
1021
+ /** Current mark-to-market value in USD (always non-null on V1 — pre-reconcile rows are excluded). */
1022
+ current_value_usd: number;
1023
+ initial_value_usd?: number | null;
1024
+ /** Unrealized P&L for the open position (Polymarket `cashPnl`). */
1025
+ cash_pnl?: number | null;
1026
+ /** Closed-leg P&L rolled up (Polymarket `realizedPnl`). */
1027
+ realized_pnl?: number | null;
1028
+ /** Max updated_at across mirror legs for this pair. */
1029
+ last_reconciled_at?: string | null;
1030
+ /** Backend-computed staleness bucket derived from last_reconciled_at. */
1031
+ freshness: "fresh" | "refreshing" | "stale" | "unknown";
1032
+ trader: {
1033
+ /** Prefixed ID (`trd_...`). */
1034
+ id: string;
1035
+ address: string;
1036
+ username?: string | null;
1037
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
1038
+ /** Percentage 0-100. */
1039
+ win_rate?: number | null;
1040
+ pnl?: number | null;
1041
+ markets?: number | null;
1042
+ wallet_age_days?: number | null;
1043
+ /** True when 0xinsider first recorded the wallet within the new-wallet threshold (30 days). This public V1 field is first-seen recency, not the wallet's on-chain age. */
1044
+ is_new_wallet: boolean;
1045
+ };
1046
+ market: {
1047
+ /** Prefixed ID (`mkt_...`). */
1048
+ id: string;
1049
+ condition_id: string;
1050
+ title: string;
1051
+ slug?: string | null;
1052
+ event_slug?: string | null;
1053
+ /** Provider-backed market_canonical category. */
1054
+ category?: string | null;
1055
+ /** Provider-reported outcome label (e.g. team name for sports). Separate from `side` because provider labels can diverge from the binary Yes/No axis. */
1056
+ outcome_label?: string | null;
1057
+ end_date?: string | null;
1058
+ };
1059
+ };
1060
+ export type PositionTimelineEvent = {
1061
+ /** Prefixed ID (pe_...). */
1062
+ id: string;
1063
+ /** ISO 8601 timestamp of the on-chain fill. */
1064
+ event_timestamp: string;
1065
+ /** From the taker's perspective. */
1066
+ action: "buy" | "sell";
1067
+ outcome_side: "yes" | "no";
1068
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for this outcome; null when unavailable (e.g. unsynced markets). */
1069
+ token_id?: string | null;
1070
+ /** Signed share delta (+ on buy, − on sell). */
1071
+ amount_delta: number;
1072
+ /** Fill price in USDC per share, in [0,1]. */
1073
+ price: number;
1074
+ /** Positive USDC notional of the fill. */
1075
+ usdc_notional: number;
1076
+ /** Polygon transaction hash of the fill. */
1077
+ tx_hash: string;
1078
+ /** Cumulative signed stored-fill amount for this outcome after this fill, including older pages. Stable across limits/cursors for unchanged source history. Excludes split, merge, redemption and neg-risk activity; not complete holdings. Incomplete fill history can also leave a negative amount. */
1079
+ running_amount: number;
1080
+ /** Cumulative buy-weighted average of stored fills for this outcome, including older pages; not provider current-position avgPrice. Sells do not change this value. 0 when no stored buys have occurred yet. */
1081
+ running_avg_price: number;
1082
+ };
1083
+ /** Policy-7 issuance binds one condition, selected token, outcome, canonical event and sport. Reuse the same authorization across public/private discovery and retries. Require a new account-size executable book and current market eligibility; this frozen reference does not prove current liquidity or positive expected value. Absence or expiry cannot authorize a new automated entry. */
1084
+ export type PotdEntryAuthorization = {
1085
+ version: 1;
1086
+ authorization_id: string;
1087
+ policy_version: 7;
1088
+ condition_id: string;
1089
+ token_id: string;
1090
+ outcome_index: 0 | 1;
1091
+ /** Canonical sport bucket, not display_category. */
1092
+ category: string;
1093
+ /** Exact provider parent event ID, or provider event ID when no parent exists. */
1094
+ canonical_event_id: string;
1095
+ /** Immutable decimal limit: first fresh selected-token ask plus 0.02, floored to the provider tick below 1. Fees excluded. Never a calibrated fair probability. */
1096
+ max_entry_price: string;
1097
+ reference_best_ask: string;
1098
+ reference_book_hash: string;
1099
+ reference_book_at: string;
1100
+ issued_at: string;
1101
+ /** Original provider kickoff ceiling. Never extended on retry. */
1102
+ expires_at: string;
1103
+ };
1104
+ /** One PUBLISHED same-day pick whose holder proof is not readable yet: its stable slot rank, the release and kickoff instants, and the instant before which a retry cannot succeed. Every item in `picks` carries its full required shape, so a pick that cannot meet it is listed here instead of being served with missing fields or a synthetic zero. */
1105
+ export type ProofPendingPickSlot = {
1106
+ /** Stable 1-based slot within the product day's ranked picks. The pick keeps this rank once its proof is readable and it moves into `picks`. */
1107
+ pick_rank: number;
1108
+ /** The pick's stored release instant. */
1109
+ release_at: string;
1110
+ /** The backed game's frozen kickoff instant; absent for a legacy row without one. */
1111
+ kickoff?: string;
1112
+ /** Recommended next read: 30 seconds ahead while pre-game proof is warming, one hour ahead for a post-kickoff pending legacy row that only settlement can make readable. Schedule against it instead of polling. */
1113
+ retry_at: string;
1114
+ };
1115
+ export type RadarFlag = {
1116
+ /** Prefixed ID (rf_...). */
1117
+ id: string;
1118
+ /** Stored score that met the live flag threshold. */
1119
+ suspicion_score: number;
1120
+ /** The live scorer persists one threshold class. */
1121
+ severity: "flag";
1122
+ trader: {
1123
+ id: string;
1124
+ address: string;
1125
+ username?: string | null;
1126
+ };
1127
+ market: {
1128
+ id: string;
1129
+ condition_id: string;
1130
+ /** Canonical market question when available. */
1131
+ title: string | null;
1132
+ };
1133
+ scores: {
1134
+ /** Null because the live scorer does not record this component. */
1135
+ timing?: number | null;
1136
+ /** Null because the live scorer does not record this component. */
1137
+ edge?: number | null;
1138
+ /** Numeric evidence.size when recorded; otherwise null. */
1139
+ size?: number | null;
1140
+ /** Numeric evidence.fresh when recorded; otherwise null. */
1141
+ fresh_wallet?: number | null;
1142
+ };
1143
+ /** Stored whale_alerts.suspicion_signals JSON from the scorer. */
1144
+ evidence: unknown;
1145
+ /** Stored trade timestamp. */
1146
+ created_at: string;
1147
+ };
1148
+ export type ReportPayload = {
1149
+ total_whale_trades?: number | null;
1150
+ total_whale_volume?: number | null;
1151
+ biggest_trade_size?: number | null;
1152
+ active_traders?: number | null;
1153
+ top_whale_trades?: ({
1154
+ /** Provider outcome label for the traded side. */
1155
+ outcome?: string | null;
1156
+ /** Trade direction (BUY or SELL), not the outcome side. */
1157
+ side?: string | null;
1158
+ /** Market title. */
1159
+ title?: string | null;
1160
+ /** Trade size in USD. */
1161
+ size?: number | null;
1162
+ /** Trade price in provider [0, 1] units. */
1163
+ price?: number | null;
1164
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the traded outcome; null when unavailable (e.g. unsynced markets). */
1165
+ token_id?: string | null;
1166
+ /** Whale trade id. */
1167
+ id?: number | null;
1168
+ /** Trade timestamp (UTC). */
1169
+ trade_time?: string | null;
1170
+ /** Provider market category. */
1171
+ market_category?: string | null;
1172
+ /** Venue: polymarket. */
1173
+ platform?: string | null;
1174
+ /** Trader display name, when known. */
1175
+ name?: string | null;
1176
+ /** Trader pseudonym, when no display name is known. */
1177
+ pseudonym?: string | null;
1178
+ /** Trader grade (S-F) at snapshot time. */
1179
+ trader_grade?: string | null;
1180
+ })[] | null;
1181
+ categories?: Record<string, unknown>[] | null;
1182
+ grade_distribution?: Record<string, unknown>[] | null;
1183
+ };
1184
+ export type ReportReconciliation = {
1185
+ volume_kind: "local_whale_activity_volume";
1186
+ whale_volume_source: "whale_alerts.usdc_notional_num";
1187
+ notes: string;
1188
+ };
1189
+ export type ReportSnapshot = {
1190
+ kind: "daily" | "weekly" | "monthly";
1191
+ generated_at: string;
1192
+ source_range: ReportSourceRange;
1193
+ snapshot: SnapshotState;
1194
+ completeness: SnapshotCompleteness;
1195
+ reconciliation: ReportReconciliation;
1196
+ report: ReportPayload;
1197
+ };
1198
+ export type ReportSourceRange = {
1199
+ start_date: string;
1200
+ end_date: string;
1201
+ timezone: "UTC";
1202
+ };
1203
+ export type ResponseMeta = {
1204
+ /** Unique request ID (req_ prefix). */
1205
+ request_id: string;
1206
+ cached: boolean;
1207
+ /** Cache age in seconds. Omitted when the response was not cached, and also when it was cached but its age cannot be established (an entry stored before its cache carried a computed instant). Never a placeholder: an unknown age is reported as no value rather than as the cache TTL. */
1208
+ cache_age_s?: number | null;
1209
+ /** Advisory request weight (relative compute cost). 1 for simple reads; higher for heavier endpoints. Not a credit/price. */
1210
+ cost: number;
1211
+ /** Committed PostgreSQL-owned leaderboard generation for the returned rows and cursor. Present on GET /api/v1/leaderboard; omitted on endpoints that do not read this ranking. */
1212
+ ranking_generation?: number | null;
1213
+ /** Authoritative RFC3339 timestamp from cache_generations.updated_at for ranking_generation. It is read in the same repeatable-read snapshot as the leaderboard rows and is not request time, cache write time, or row insertion order. */
1214
+ ranking_as_of?: string | null;
1215
+ /** Which path produced the team-directional read on this response. Only present on endpoints that compute one (today: GET /api/v1/sports-edge-signals). "live" means the read RAN. "degraded" means it FAILED, so nothing was measured and the ranking fell back to raw conviction. The flag describes the READ, not its consequence: a read that ran and found nothing groupable also leaves the directional fields null, and that is honestly "live" -- the per-signal nulls already say "nothing to enrich here", so this snapshot-level flag carries only what they cannot, namely whether the read ran at all. A degraded response is cached on the shorter degraded TTL so it self-heals. Reported SEPARATELY from ranking_source because the two degradations are independent -- a smart-money DB miss weakens the ranking DATA, a directional failure removes a ranking WEIGHT -- and a consumer down-weighting a degraded response needs to know which input it lost. Omitted on endpoints that compute no directional read. */
1216
+ directional_source?: "live" | "degraded";
1217
+ /** Which ranking-data path produced this response. Only present on endpoints that can degrade a ranking (today: GET /api/v1/sports-edge-signals). "live" is the normal path (the current holder pile from the provider batch); "db_only" is the degraded fallback (a truthful but weaker trader_markets ranking) served when the live sharp-money ranking batch is unavailable (a smart-money DB read failure, not a Polymarket outage) and cached on a shorter TTL, so a consumer can down-weight or skip it. Omitted on endpoints that never degrade. */
1218
+ ranking_source?: "live" | "db_only";
1219
+ /** Whole filtered snapshot category-evidence status before pagination. Operational live always remains partial source coverage. */
1220
+ category_skill_source?: "live" | "partial" | "degraded" | "unavailable";
1221
+ category_skill_model_version?: string;
1222
+ category_skill_taxonomy_version?: string;
1223
+ category_skill_platform?: "polymarket";
1224
+ category_skill_scope?: "observed_goldsky_primary_taker_fill";
1225
+ category_skill_source_coverage?: "partial_whale_threshold_fills" | "graded_wallet_fills";
1226
+ category_skill_observation_started_at?: string;
1227
+ /** Whole-model operational readiness captured with the category model snapshot. Present on category-enriched responses even when the filtered signal list is empty. When true, category_skill_source is degraded and sports-edge-signals uses the shorter degraded cache TTL. */
1228
+ category_skill_model_operationally_degraded?: boolean;
1229
+ category_skill_status_counts?: {
1230
+ live: number;
1231
+ insufficient: number;
1232
+ stale: number;
1233
+ unknown: number;
1234
+ degraded: number;
1235
+ };
1236
+ /** SHA-256 of the funded signal membership/order/rank/cursor vector immediately before category-skill enrichment. Sports-edge-signals only. */
1237
+ category_skill_base_payload_hash?: string;
1238
+ /** Independent SHA-256 recomputation over the same base fields immediately after category-skill enrichment. Equality with category_skill_base_payload_hash proves shadow enrichment did not change funded inputs. Sports-edge-signals only. */
1239
+ category_skill_enriched_base_payload_hash?: string;
1240
+ };
1241
+ /** One same-day pick that is selected but not yet released: its stable slot rank plus the backend-owned release and kickoff instants. Deliberately minimal -- no matchup, category, platform, side, price, or holder fields exist on this shape before release. */
1242
+ export type ScheduledPickSlot = {
1243
+ /** Stable 1-based slot within the product day's ranked picks. The slot keeps this rank when it releases. */
1244
+ pick_rank: number;
1245
+ /** The slot's scheduled release instant, normally the current provider kickoff minus one hour. The actual publish can trail it by bounded worker delay. */
1246
+ release_at: string;
1247
+ /** The backed game's current kickoff instant. */
1248
+ kickoff: string;
1249
+ };
1250
+ /** One side's score in a single set. The verbatim provider text stays on the team's `score` string; this is the parsed form. */
1251
+ export type ScoreCell = {
1252
+ /** Games won in this set. */
1253
+ games: number;
1254
+ /** Tiebreak points won in this set. Omitted when the set had no tiebreak; absence and zero are different. */
1255
+ tiebreak?: number;
1256
+ };
1257
+ /** Shape the provider score string was parsed into. `two_side` is one aggregate per side (basketball `105-98`), `multi_set` is per-set columns (tennis `6-7(5-7), 6-0, 1-0`), `esports_series` is a maps/sets/format triplet (`000-000|2-0|Bo3`). Omitted when the score could not be parsed. */
1258
+ export type ScoreFormat = "two_side" | "multi_set" | "esports_series";
1259
+ export type SmartMoneyFlowMarket = {
1260
+ market: {
1261
+ id: string;
1262
+ condition_id: string;
1263
+ title: string | null;
1264
+ slug: string | null;
1265
+ category: string | null;
1266
+ platform: string | null;
1267
+ };
1268
+ /** Sharp-money flow aggregate for the market (canonical; smart_money is a deprecated byte-identical alias). */
1269
+ sharp_money: {
1270
+ net_flow_usd: number;
1271
+ direction: "YES" | "NO";
1272
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
1273
+ token_id?: string | null;
1274
+ whale_trade_count: number;
1275
+ buy_volume_usd: number;
1276
+ sell_volume_usd: number;
1277
+ };
1278
+ /** Deprecated alias of sharp_money; byte-identical and retained for backward compatibility. */
1279
+ smart_money: {
1280
+ net_flow_usd: number;
1281
+ direction: "YES" | "NO";
1282
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the net-flow direction outcome; null when unavailable (e.g. unsynced markets). */
1283
+ token_id?: string | null;
1284
+ whale_trade_count: number;
1285
+ buy_volume_usd: number;
1286
+ sell_volume_usd: number;
1287
+ };
1288
+ timeframe: string;
1289
+ };
1290
+ export type SnapshotCompleteness = {
1291
+ status: "complete" | "partial" | "empty";
1292
+ reason: string;
1293
+ expected_days: number;
1294
+ covered_days_with_whale_activity: number;
1295
+ };
1296
+ export type SnapshotState = {
1297
+ /** Immutable content version for this report identity. */
1298
+ version: number;
1299
+ status: "final" | "rolling";
1300
+ generated_at: string;
1301
+ mutable_until?: string | null;
1302
+ };
1303
+ /** Per-sport accountable funnel for the full observation snapshot, returned on every page. */
1304
+ export type SportsEdgeFunnelReport = {
1305
+ sports: SportsEdgeSportFunnelReport[];
1306
+ };
1307
+ /** One explicitly observation-only holder-pile measurement. It is evidence for cohort evaluation, not an execution instruction, and is isolated from the funded sports-edge-signals route. */
1308
+ export type SportsEdgeObservation = {
1309
+ /** Raw Polymarket condition id. */
1310
+ condition_id: string;
1311
+ /** Provider-backed Polymarket CLOB token id for the piled outcome. Rows without a verified token terminate before emission. */
1312
+ token_id: string;
1313
+ /** Canonical sport bucket. */
1314
+ category: "Basketball" | "Football" | "Baseball" | "Hockey" | "MMA" | "Boxing" | "Soccer" | "Cricket" | "Golf" | "Tennis" | "Esports" | "Racing" | "Table Tennis" | "Pickleball";
1315
+ /** Raw provider category as stored. */
1316
+ raw_category: string | null;
1317
+ /** Provider-backed market title. */
1318
+ title: string;
1319
+ event_slug: string | null;
1320
+ /** Provider event id when available. */
1321
+ event_id: string | null;
1322
+ /** Provider parent-event id used as the first event-cap identity when available. */
1323
+ parent_event_id: string | null;
1324
+ /** Provider-backed kickoff time in UTC. */
1325
+ game_start_time: string;
1326
+ /** UTC instant when this row finished provider/holder evaluation. */
1327
+ observed_at: string;
1328
+ /** Source cohort or additive projection view. emerging_pile is projected from wider_holder after source computation, overlaps its funnel denominator, and uses the source row's directional evidence. */
1329
+ cohort: "wider_holder" | "in_play" | "emerging_pile";
1330
+ /** Always true. This row must not be routed to an order executor. */
1331
+ observation_only: true;
1332
+ /** Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. */
1333
+ piled_side: string | null;
1334
+ /** Provider binary-column selector: 0 selects outcome_yes/token_id_yes; 1 selects outcome_no/token_id_no. It does not identify home/away or a participant. Use piled_side together with title/event context for display. */
1335
+ piled_outcome_index: 0 | 1;
1336
+ /** Provider-backed implied price for the piled outcome at observation time. */
1337
+ backed_price: number;
1338
+ /** Piled-side graded-holder dollar concentration. */
1339
+ sharp_pct: number;
1340
+ /** Raw graded-holder USD on the piled outcome. */
1341
+ backed_sharp_usd: number;
1342
+ s_count: number;
1343
+ a_count: number;
1344
+ b_count: number;
1345
+ /** Piled-side S/A/B holder count. */
1346
+ graded_holders: number;
1347
+ top_grade: "S" | "A" | "B";
1348
+ /** Canonical signed holder-pile score. */
1349
+ smart_score: number;
1350
+ /** Strictly positive stored market volume in USD. Missing, zero, or non-finite volume terminates as invalid_market and is never emitted as an observation. */
1351
+ volume: number;
1352
+ /** Grade-weighted holder-pile score before directional enrichment. */
1353
+ conviction_score: number;
1354
+ /** Whether the provider holder page came from the shared cache or a live provider read. */
1355
+ provider_read_source: "cached" | "live";
1356
+ /** True only when neither provider outcome holder page hit the top-100 scan bound. False means the pile is a positive lower bound and cannot satisfy a future capital-promotion gate. */
1357
+ holder_scan_complete: boolean;
1358
+ /** Proven provider holder observation time. A warm cache hit uses only the original provider completion time from its companion metadata, never cache-read time. Null, malformed, future, or stale holder time fails in-play closed. */
1359
+ holder_snapshot_at: string | null;
1360
+ /** Truthful state of the directional read, which classifies each graded holder by its fresh synced legs across the game's markets and, when holder_scan_complete is true, by Polymarket's currentValue on both outcomes of this market. A wider_holder row can remain emitted with unavailable and terminal wider_holder_emitted; in_play fails closed instead and terminates as in_play_directional_unavailable. */
1361
+ directional_status: "available" | "unknown_ungrouped" | "unknown_stale" | "unavailable";
1362
+ one_way_holder_count: number | null;
1363
+ hedged_holder_count: number | null;
1364
+ one_way_graded_usd: number | null;
1365
+ directional_confidence: number | null;
1366
+ /** Default cohort ordering key: conviction_score * (1 + 0.25 * directional_confidence), or conviction_score when confidence is null. */
1367
+ directional_rank_score: number;
1368
+ /** 1-based rank within this observation cohort and snapshot. */
1369
+ rank: number;
1370
+ };
1371
+ /** Closed 25-value terminal-reason vocabulary for the accountable sports-edge observation funnel. capacity_limited is intentional bounded provider-work admission and does not itself set the snapshot degraded. board_source_unavailable is a completed board-source failure; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; both classify only already-started rows, so for the upcoming source read funnel.sports[].board_upcoming_status instead; provider_unavailable is reserved for an attempted holder-provider failure; holder_deadline_unavailable is holder cache/provider absolute-deadline exhaustion. */
1372
+ export type SportsEdgeObservationTerminalReason = "outside_horizon" | "resolved" | "provider_closed" | "provider_excluded" | "invalid_market" | "missing_token" | "missing_stored_market" | "not_provider_live" | "board_source_unavailable" | "board_deadline_unavailable" | "primary_slate_candidate" | "zero_indexed_holder_research" | "capacity_limited" | "provider_unavailable" | "holder_deadline_unavailable" | "holder_computation_unavailable" | "holder_scan_incomplete" | "no_current_graded_holder" | "split_holder_pile" | "price_unavailable" | "wider_holder_emitted" | "in_play_emitted" | "in_play_stale_observed" | "in_play_directional_unavailable" | "internal_unclassified";
1373
+ /** One ranked pre-game sports market where graded sharp money is piled on one side, with required-status shadow category evidence from partial forward-observed Polymarket fills. */
1374
+ export type SportsEdgeSignal = {
1375
+ /** Polymarket condition id. */
1376
+ condition_id: string;
1377
+ /** UTC time at which the immutable signal snapshot was computed. Every row from one snapshot shares this value; it is not provider market creation time and is not rewritten at request time. */
1378
+ signal_created_at: string;
1379
+ /** Polymarket CLOB token id (ERC1155 asset id, decimal string) for the PILED outcome; null when unavailable. */
1380
+ token_id?: string | null;
1381
+ /** Canonical sport bucket (e.g. Basketball, Tennis); null when the raw category has no canonical mapping. */
1382
+ category?: string | null;
1383
+ /** Raw provider category as stored (e.g. NBA, EPL). */
1384
+ raw_category?: string | null;
1385
+ title?: string | null;
1386
+ event_slug?: string | null;
1387
+ /** Kickoff (UTC). In the future at SNAPSHOT time and within the requested horizon; because the response is served from a shared snapshot cached up to the ~180s TTL, a served kickoff can be up to ~180s in the past relative to the response time. Not a live guarantee that the game has not yet started. */
1388
+ game_start_time?: string | null;
1389
+ /** Nullable provider-backed piled-outcome display label. When provider group context is unavailable, it may remain a bare Yes/No/Over/Under; do not use it alone as participant identity. */
1390
+ piled_side?: string | null;
1391
+ /** Provider binary-column selector: 0 selects outcome_yes/token_id_yes; 1 selects outcome_no/token_id_no. It does not identify home/away or a participant. Use piled_side together with title/event context for display. */
1392
+ piled_outcome_index: number;
1393
+ /** Piled-side dollar concentration backed_usd / (yes_usd + no_usd), in (0.5, 1] for a real pile; null when there is no sharp USD. */
1394
+ sharp_pct?: number | null;
1395
+ /** Raw piled-side sharp-money USD. */
1396
+ backed_sharp_usd: number;
1397
+ /** S-grade graded holders on the piled side. */
1398
+ s_count: number;
1399
+ /** A-grade graded holders on the piled side. */
1400
+ a_count: number;
1401
+ /** B-grade graded holders on the piled side. */
1402
+ b_count: number;
1403
+ /** Piled-side graded holder count (s_count + a_count + b_count). */
1404
+ graded_holders: number;
1405
+ /** Best grade present on the piled side; null when none. */
1406
+ top_grade?: "S" | "A" | "B";
1407
+ /** Canonical sharp-money score (yes_usd - no_usd)/(yes_usd + no_usd) in [-1, 1] (piled-yes positive, piled-no negative); a lower-order ranking tiebreak (after directional_rank_score and conviction_score). */
1408
+ smart_score?: number | null;
1409
+ /** Market volume (USD). */
1410
+ volume?: number | null;
1411
+ /** Aggregate recent flow direction on the market; null when unavailable. */
1412
+ net_side?: "BUY" | "SELL";
1413
+ /** Grade-weighted pile score (5*s + 4*a + 3*b) * sharp_pct; the raw conviction input to the ranking (see directional_rank_score). */
1414
+ conviction_score: number;
1415
+ /** Piled-side graded holders read one-way: their fresh open legs across the signal game's markets (cross-market within the one game; moneyline+spread family only) all back the same team, or, when the market's holder scan was complete, Polymarket's currentValue shows no opposite leg on this market worth 10% of the backed leg and no fresh leg opposes it. Null when the directional read was not computed (no groupable game, no holder-level data on this ranking path, or the enrichment read failed) or classified nobody. */
1416
+ one_way_holder_count?: number | null;
1417
+ /** Piled-side graded holders classified HEDGED across the game by fresh legs (they back two or more distinct teams). A wallet long both outcomes of this market is not one-way and not counted here. Null when the directional read was not computed or classified nobody. */
1418
+ hedged_holder_count?: number | null;
1419
+ /** Piled-side graded USD held by one-way wallets (share-weighted allocation of backed_sharp_usd). Null when the directional read was not computed or classified nobody. */
1420
+ one_way_graded_usd?: number | null;
1421
+ /** One-way fraction of the piled graded dollars, in [0, 1] -- the metric orthogonal to sharp_pct. Stale, unknown, hedged, and two-sided dollars dilute it toward zero (conservative). Null when the directional read was not computed or classified nobody. */
1422
+ directional_confidence?: number | null;
1423
+ /** The ranking key, descending: conviction_score * (1 + 0.25 * directional_confidence). Equals conviction_score when the directional read is null/zero, so signals without the read rank exactly as before. */
1424
+ directional_rank_score: number;
1425
+ category_skill: SportsEdgeSignalCategorySkill;
1426
+ /** 1-based rank within the (min_grade-filtered) ranked result. */
1427
+ rank: number;
1428
+ };
1429
+ /** Shadow-only category evidence over the full uncapped piled-side S/A/B holder allocation. It never changes signal membership, ordering, routing, or sizing. */
1430
+ export type SportsEdgeSignalCategorySkill = {
1431
+ status: "live" | "insufficient" | "stale" | "unknown" | "degraded";
1432
+ model_version: string;
1433
+ taxonomy_version: string | null;
1434
+ platform: "polymarket";
1435
+ scope: "observed_goldsky_primary_taker_fill";
1436
+ source_coverage: "partial_whale_threshold_fills" | "graded_wallet_fills";
1437
+ observation_started_at: string;
1438
+ as_of: string;
1439
+ canonical_category: string | null;
1440
+ eligible_holders: number;
1441
+ covered_holders: number;
1442
+ backed_sharp_usd: number | null;
1443
+ covered_backed_usd: number | null;
1444
+ coverage_pct: number | null;
1445
+ weighted_edge_mean: number | null;
1446
+ weighted_holder_lower_mean: number | null;
1447
+ specialist_backed_usd: number | null;
1448
+ specialist_backed_usd_pct: number | null;
1449
+ largest_holder_backed_usd_pct: number | null;
1450
+ minimum_holder_event_count: number | null;
1451
+ };
1452
+ /** Independent sports-board supply plus stored-universe terminal accounting for one canonical sport. */
1453
+ export type SportsEdgeSportFunnelReport = {
1454
+ sport: "Basketball" | "Football" | "Baseball" | "Hockey" | "MMA" | "Boxing" | "Soccer" | "Cricket" | "Golf" | "Tennis" | "Esports" | "Racing" | "Table Tennis" | "Pickleball";
1455
+ /** Unique condition ids independently visible on the provider-first sports board. */
1456
+ board_input: number;
1457
+ /** Whether the always-applicable live-board source completed as available. False can mean a completed source failure (board_source_unavailable) or live-board work missing an internal configured-scope deadline or the outer fair-wave deadline (board_deadline_unavailable); inspect terminals to distinguish them. */
1458
+ board_live_available: boolean;
1459
+ /** Whether a provider-backed upcoming-board source is configured and applicable for this sport. False means not applicable, not provider failure. */
1460
+ board_upcoming_configured: boolean;
1461
+ /** Whether every configured upcoming-board scope completed as available. False with board_upcoming_configured=false means not applicable. When board_upcoming_configured is true and this flag is false, read board_upcoming_status for the cause (it reads unknown, i.e. no recorded cause, only on a snapshot cached before that field existed, which self-clears within one TTL): the board_source_unavailable and board_deadline_unavailable terminals are assigned only to already-started rows (the live half) and are structurally 0 for the upcoming source, so they never explain this flag. */
1462
+ board_upcoming_available: boolean;
1463
+ /** Why the upcoming-board source is (un)available. Board supply is one canonical-sport union: the bare category owns live truth and every configured composed league scope contributes upcoming rows; folded leagues without a configured board (currently NCAAB and CFL) are not in the upcoming union. available: every configured scope completed truthfully (a successful empty schedule still counts). capacity_limited: provider pagination or a configured upcoming cache published an intentionally bounded complete-event prefix; those rows are excluded from diagnostic-universe input and must not be treated as a complete upcoming universe. Cache-bound prefixes are limited to 3,000 rows or an exact 5,000,000-byte final envelope. source_unavailable: composition failed before a truthful union; resolved scope readers turn half failures into cold_unavailable, so fresh producers are whole-union identity reconciliation or a registry contract failure and carry zero rows. cold_unavailable: every scope completed but at least one reported its upcoming half unavailable because no servable entry was inside the stale-serve bound and the background warm did not land in time; it is not by itself proof of a provider outage. deadline_unavailable: an internal configured-scope deadline or the outer bounded fair wave expired. An internal deadline may retain healthy bare-category or sibling-scope rows; the outer wave records zero rows. These upcoming fields do not describe league live-membership availability. If the bare-category live scope fails, all live rows are dropped even when a league scope completed, because the bare category is the sole live-truth owner. not_configured: no upcoming scope applies to the sport. unknown: exactly one cause -- a snapshot cached before this field existed whose legacy flags recorded an unavailable-but-configured half without saying why. Every freshly computed snapshot reports a concrete status, and a legacy available or not-configured row is reconstructed exactly, so unknown self-clears within one TTL. board_upcoming_available is exactly board_upcoming_status == available. */
1464
+ board_upcoming_status: "unknown" | "not_configured" | "available" | "capacity_limited" | "source_unavailable" | "cold_unavailable" | "deadline_unavailable";
1465
+ /** Configured upcoming scopes that did not complete as available. Values are category, a provider league tag slug (nfl, cfb, nba, wnba, nhl, mls, valorant, league-of-legends, counter-strike-2, or dota-2), registry when the compiled scope/projection contract drifted, union when cross-scope identity reconciliation failed, or wave when the outer fair-wave deadline expired before scope-level evidence returned. Empty means no unavailable upcoming scope was identified; this includes healthy/not-configured rows and a legacy cached row. Observation league scopes are upcoming-only and perform no live-membership read. */
1466
+ board_upcoming_unavailable_scopes: ("category" | "nfl" | "cfb" | "nba" | "wnba" | "nhl" | "mls" | "valorant" | "league-of-legends" | "counter-strike-2" | "dota-2" | "registry" | "union" | "wave")[];
1467
+ /** Stored-universe rows plus provider-board rows missing from storage. */
1468
+ input: number;
1469
+ /** Sparse counts over the closed 25-value terminal vocabulary: outside_horizon, resolved, provider_closed, provider_excluded, invalid_market, missing_token, missing_stored_market, not_provider_live, board_source_unavailable, board_deadline_unavailable, primary_slate_candidate, zero_indexed_holder_research, capacity_limited, provider_unavailable, holder_deadline_unavailable, holder_computation_unavailable, holder_scan_incomplete, no_current_graded_holder, split_holder_pile, price_unavailable, wider_holder_emitted, in_play_emitted, in_play_stale_observed, in_play_directional_unavailable, or internal_unclassified. primary_slate_candidate means exact admission by the funded route's raw shared signals query before provider/holder enrichment; recent-flow rows rejected by its event, bucket, or total caps remain eligible for wider_holder measurement. capacity_limited is intentional bounded provider-work admission, is fully accounted here, and does not itself set degraded=true. board_source_unavailable means a completed board source was unavailable; board_deadline_unavailable means live-board work missed either an internal configured-scope deadline or the outer fair-wave deadline; provider_unavailable means an attempted holder-provider read failed; holder_deadline_unavailable means holder cache/provider work missed the absolute request deadline; holder_computation_unavailable means post-holder provider or DB-backed price/metadata evaluation was unavailable. */
1470
+ terminals: Record<string, number>;
1471
+ /** Sum of every sparse terminal count. */
1472
+ terminal_total: number;
1473
+ /** True exactly when input equals terminal_total. */
1474
+ reconciled: boolean;
1475
+ };
1476
+ export type Trader = {
1477
+ /** Prefixed ID (trd_...). */
1478
+ id: string;
1479
+ address: string;
1480
+ username?: string | null;
1481
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
1482
+ /** Hot-streak tier (trailing-7d cross-sectional percentile); a separate axis from the all-time grade. Null when no recent activity. */
1483
+ streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
1484
+ score?: number | null;
1485
+ rank?: number | null;
1486
+ pnl: {
1487
+ total?: number | null;
1488
+ /** For pnl.realized, expand=trust marks a matching native accounting snapshot as computed: native Polymarket realized P&L plus credited maker and taker rebates, with fees already included. Without a matching native accounting snapshot, pnl.realized is omitted and its trust metadata is unavailable. Raw total P&L is never substituted for realized P&L. */
1489
+ realized?: number | null;
1490
+ unrealized?: number | null;
1491
+ /** DEPRECATED, always null. The local pnl_7d rollup over-counted P&L (#5416 class) and is no longer emitted. Read the provider-native weekly window from GET /api/trader/{address}/profile-summary instead. */
1492
+ last_7d?: number | null;
1493
+ /** DEPRECATED, always null. The local pnl_30d rollup over-counted P&L (#5416 class) and is no longer emitted. Read the provider-native monthly window from GET /api/trader/{address}/profile-summary instead. */
1494
+ last_30d?: number | null;
1495
+ };
1496
+ stats: {
1497
+ markets_traded?: number | null;
1498
+ win_rate?: number | null;
1499
+ daily_win_rate?: number | null;
1500
+ total_volume?: number | null;
1501
+ };
1502
+ strategy?: {
1503
+ strategy_type?: string;
1504
+ description?: string | null;
1505
+ confidence?: number | null;
1506
+ } | null;
1507
+ /** Per-category performance breakdown (expand=categories or expand[]=categories). Omitted unless expanded. Object keyed by category name; each value is the precomputed trader_rankings.category_ranks payload (rank, total_in_category, total_pnl, scaled_total_pnl, n_markets, wins, losses, win_rate; scaled_total_pnl is a legacy alias that currently equals total_pnl). Pass-through DB JSON: keys and value shape are DB-owned, so the inner shape is intentionally unconstrained and may carry additional compatibility fields. */
1508
+ category_strengths?: Record<string, unknown> | null;
1509
+ /** Curated advanced risk/performance metrics (expand=quant_metrics or expand[]=quant_metrics). Omitted unless expanded and backed by a computed row strictly under six hours old; a missing row, NULL computed_at, or age of exactly six hours or more is stale and omitted. Provider-input changes may intentionally lag inside the bounded six-hour window. When present, all listed fields are present (each is a number or null); null means insufficient trade history and must not be treated as 0. The fixed field shape is unchanged. */
1510
+ quant_metrics?: {
1511
+ /** Composite skill score, 0-100. smart_score = clamp(0, 100, 30*sharpe_percentile_fraction + 20*profit_factor_percentile_fraction + 20*edge_consistency_percentile_fraction + 10*min(1, return_on_capital/2) + 10*equity_smoothness + 10*(1 - min(1, asset_concentration))). Higher is better. null when insufficient history. */
1512
+ smart_score: number | null;
1513
+ /** Copyability score, 0-100. Same base as smart_score minus penalties for traits that make a strategy hard to replicate: -20 if fewer than 50 markets traded, -15 if positions are highly concentrated, -15 if position sizing exceeds about 2x Kelly, -10 if the worst single-trade loss exceeds 30%, -10 if edge is inconsistent; result clamped to 0-100. Higher means easier to follow. null when insufficient history. */
1514
+ copy_score: number | null;
1515
+ /** Sharpe ratio over the trailing 30 days (risk-adjusted return; higher is better). Magnitude can be large for small samples. null when insufficient history. */
1516
+ sharpe_30d: number | null;
1517
+ /** Sharpe ratio over the trailing 7 days (risk-adjusted return; higher is better). null when insufficient history. */
1518
+ sharpe_7d: number | null;
1519
+ /** Gross profit divided by gross loss; greater than 1 is profitable. Capped at 1000 when there are effectively no losses. null when insufficient history. */
1520
+ profit_factor: number | null;
1521
+ /** Stability of the trader's edge over time, 0-1 (higher is more consistent). null when insufficient history. */
1522
+ edge_consistency: number | null;
1523
+ /** Cross-sectional percentile rank of the trader's Sharpe ratio versus all traders, 0-100. null when insufficient history. */
1524
+ sharpe_percentile: number | null;
1525
+ /** Cross-sectional percentile rank of profit factor versus all traders, 0-100. null when insufficient history. */
1526
+ pf_percentile: number | null;
1527
+ /** Cross-sectional percentile rank of edge consistency versus all traders, 0-100. null when insufficient history. */
1528
+ consistency_percentile: number | null;
1529
+ } | null;
1530
+ last_active?: string | null;
1531
+ synced_at?: string | null;
1532
+ /** synced, unknown, or pending. */
1533
+ sync_status?: string | null;
1534
+ /** Field-level trust metadata. Present only when expand=trust or expand[]=trust is requested. */
1535
+ trust?: TraderTrust;
1536
+ };
1537
+ export type TraderContext = {
1538
+ trader: Trader;
1539
+ /** Aggregate position and P&L coverage for the trader. Omitted entirely (key absent, never null) when the trader is not in the local database or native net economics is unavailable. Realized fields remain numbers when present, including a genuine zero. */
1540
+ position_summary?: {
1541
+ /** Provider markets_traded count when known; null when the provider total is unavailable. */
1542
+ markets_total: number | null;
1543
+ /** Markets with locally synced position rows. */
1544
+ markets_synced: number;
1545
+ /** Synced markets that have resolved. */
1546
+ markets_resolved: number;
1547
+ /** Synced markets still open with residual value (open positions with current value > 0). */
1548
+ markets_open: number;
1549
+ /** markets_synced divided by markets_total when the provider total is known (capped at 1.0); 0.0-1.0. When markets_total is unknown or not positive (null, 0, or negative), this is 1.0 if any markets are synced (else 0.0), so cross-check markets_total before treating 1.0 as full coverage. */
1550
+ sync_coverage: number;
1551
+ /** Native net realized P&L (USD) including credited rebates, minus the stored realized component of open positions with positive current value. Rebates are credited to the account, not to a position, so every credited rebate stays in this figure. NUMERIC arithmetic precedes conversion to a JSON number. */
1552
+ synced_realized_pnl: number;
1553
+ /** Native net realized P&L (USD) including credited rebates, read directly from the accounting snapshot. Position sync_coverage is separate from this accounting basis. */
1554
+ total_realized_pnl: number;
1555
+ /** Mark-to-market unrealized P&L (USD) on open positions. */
1556
+ unrealized_mtm: number;
1557
+ /** Cost basis (USD) currently tied up in open positions. */
1558
+ cost_basis_locked: number;
1559
+ /** Win rate as a percentage (0-100): resolved_wins over resolved_decided. A resolved market that settled at exactly zero realized P&L (a void, a refund, a fully hedged position) is neither a win nor a loss and is not in the denominator, the same rule the leaderboard applies; null when no resolved market was decided. */
1560
+ resolved_win_rate: number | null;
1561
+ /** Resolved markets that settled at positive realized P&L: the win-rate numerator. Additive; null only on a summary cached before the field existed. */
1562
+ resolved_wins?: number | null;
1563
+ /** Resolved markets that settled at a non-zero realized P&L: the win-rate denominator. At most markets_resolved; the difference is markets settled at exactly zero or with an unknown P&L. Additive; null only on a summary cached before the field existed. */
1564
+ resolved_decided?: number | null;
1565
+ /** RFC3339 freshness of the served OPEN-position data: the trader's latest /positions snapshot, else the last completed sync. The snapshot advances ONLY open positions, so read this as the open-position freshness clock -- the resolved/closed aggregates on this same summary (markets_resolved, resolved_win_rate) advance only on a full sync. The value is the /positions snapshot instant when one exists, so it is typically at or just before the trader-level last sync on a normal sync, and can be AFTER it while the active-view loop refreshes open positions between full syncs. This clock does not establish native accounting freshness. Always present on the wire (serialized as JSON null when the trader has neither a snapshot nor a sync); never omitted. */
1566
+ as_of: string | null;
1567
+ };
1568
+ /** RFC3339 freshness of the OPEN-position-level data: when a position_summary is present this mirrors its as_of byte-for-byte (latest /positions snapshot, else last completed sync) -- the open-position freshness clock, since the snapshot advances only open positions; otherwise the trader's last completed sync, even if an unserved position snapshot exists. Null when the selected clock is unavailable; a missing breakdown does not establish position or accounting freshness. */
1569
+ data_as_of: string | null;
1570
+ /** 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 date to the last full sync; native realized P&L follows its accounting snapshot -- not a live feed; re-fetch for fresher data). */
1571
+ freshness_note: string;
1572
+ };
1573
+ export type TraderExportJob = {
1574
+ object: "trader_export_job";
1575
+ data: {
1576
+ job_id: number;
1577
+ status: "queued" | "running" | "ready" | "failed";
1578
+ format: "json" | "ndjson" | "csv";
1579
+ total_trades?: number | null;
1580
+ processed_trades?: number | null;
1581
+ file_size?: number | null;
1582
+ error?: string | null;
1583
+ };
1584
+ meta: ResponseMeta;
1585
+ };
1586
+ export type TraderExportSnapshot = {
1587
+ address: string;
1588
+ generated_at: string;
1589
+ source_range: ExportSourceRange;
1590
+ completeness: ExportCompleteness;
1591
+ reconciliation: ExportVolumeReconciliation;
1592
+ counts: ExportCounts;
1593
+ large_export_policy: LargeExportPolicy;
1594
+ };
1595
+ export type TraderPnl = {
1596
+ /** Prefixed trader ID (`trd_...`). */
1597
+ id: string;
1598
+ /** RFC3339 served-freshness clock for this trader's PnL history = traders.daily_pnl_recomputed_at, when the daily_pnl read model this response is served from was last rebuilt; null when it has never been recomputed for the trader. Additive optional (not in `required`). */
1599
+ freshness_at?: string | null;
1600
+ /** Daily cumulative-P&L series (oldest-first). */
1601
+ entries: ({
1602
+ date: string;
1603
+ markets_traded?: number | null;
1604
+ total_volume?: number | null;
1605
+ cumulative_profit?: number | null;
1606
+ total_pnl?: number | null;
1607
+ daily_change: number;
1608
+ })[];
1609
+ stats: {
1610
+ all: {
1611
+ current: number;
1612
+ change: number;
1613
+ change_pct: number;
1614
+ best_day: number;
1615
+ best_day_date?: string | null;
1616
+ worst_day: number;
1617
+ worst_day_date?: string | null;
1618
+ win_days: number;
1619
+ loss_days: number;
1620
+ avg_day: number;
1621
+ rebase_anchor: number;
1622
+ };
1623
+ d90: {
1624
+ current: number;
1625
+ change: number;
1626
+ change_pct: number;
1627
+ best_day: number;
1628
+ best_day_date?: string | null;
1629
+ worst_day: number;
1630
+ worst_day_date?: string | null;
1631
+ win_days: number;
1632
+ loss_days: number;
1633
+ avg_day: number;
1634
+ rebase_anchor: number;
1635
+ };
1636
+ d30: {
1637
+ current: number;
1638
+ change: number;
1639
+ change_pct: number;
1640
+ best_day: number;
1641
+ best_day_date?: string | null;
1642
+ worst_day: number;
1643
+ worst_day_date?: string | null;
1644
+ win_days: number;
1645
+ loss_days: number;
1646
+ avg_day: number;
1647
+ rebase_anchor: number;
1648
+ };
1649
+ d7: {
1650
+ current: number;
1651
+ change: number;
1652
+ change_pct: number;
1653
+ best_day: number;
1654
+ best_day_date?: string | null;
1655
+ worst_day: number;
1656
+ worst_day_date?: string | null;
1657
+ win_days: number;
1658
+ loss_days: number;
1659
+ avg_day: number;
1660
+ rebase_anchor: number;
1661
+ };
1662
+ };
1663
+ /** Per-month P&L aggregation. */
1664
+ monthly: {
1665
+ year: number;
1666
+ month: number;
1667
+ pnl: number;
1668
+ markets_traded: number;
1669
+ }[];
1670
+ /** Per-year P&L totals (ascending by year). */
1671
+ year_totals: {
1672
+ year: number;
1673
+ pnl: number;
1674
+ }[];
1675
+ /** Underwater (drawdown) series. */
1676
+ drawdown: {
1677
+ date: string;
1678
+ cumulative_profit: number;
1679
+ drawdown: number;
1680
+ }[];
1681
+ };
1682
+ /** Field-level trust metadata returned only when GET /api/v1/trader/{address} includes expand=trust. */
1683
+ export type TraderTrust = {
1684
+ total_pnl: TrustMetadata;
1685
+ realized_pnl: TrustMetadata;
1686
+ unrealized_pnl: TrustMetadata;
1687
+ markets_traded: TrustMetadata;
1688
+ win_rate: TrustMetadata;
1689
+ daily_win_rate: TrustMetadata;
1690
+ total_volume: TrustMetadata;
1691
+ grade: TrustMetadata;
1692
+ score: TrustMetadata;
1693
+ rank: TrustMetadata;
1694
+ streak_tier: TrustMetadata;
1695
+ strategy: TrustMetadata;
1696
+ category_strengths: TrustMetadata;
1697
+ quant_metrics: TrustMetadata;
1698
+ last_active: TrustMetadata;
1699
+ synced_at: TrustMetadata;
1700
+ sync_status: TrustMetadata;
1701
+ };
1702
+ export type TrendingWallet = {
1703
+ /** Prefixed trader ID (`trd_...`). */
1704
+ id: string;
1705
+ address: string;
1706
+ /** 1-based rank within the full ranked set (stable across pages). */
1707
+ rank: number;
1708
+ username?: string | null;
1709
+ /** Official Polymarket avatar URL (profileImage). */
1710
+ profile_image_url?: string | null;
1711
+ /** Real provider platform; surfaced, never coerced. Polymarket-only today. */
1712
+ platform: "polymarket";
1713
+ /** Polymarket weekly/monthly P&L for the wallet in USD, taken from Polymarket's canonical leaderboard (data-api.polymarket.com/v1/leaderboard?timePeriod=week|month&orderBy=PNL). This is the ranking axis and the rows are returned in Polymarket's by-PNL order; it is the provider's number, not a locally summed realized-leaf total. */
1714
+ trending_pnl_usd: number;
1715
+ window_volume_usd: number;
1716
+ window_markets_traded: number;
1717
+ /** Distinct in-window UTC trade days from our trades (0 if the winner is not in our DB). */
1718
+ window_trade_days: number;
1719
+ /** All-time trader grade; a separate axis from streak_tier. Led by realized profit (the money actually banked, about 95 percent of the grade), with forecasting calibration, risk-adjusted returns, and consistency as the tie-breaker and proven-trader guardrails: any grade above C requires verified net-positive realized profit, and the top grades also require a real resolved-market track record plus a survivable drawdown. Relative, so it drifts as the cohort moves. Omitted when the trader is Unranked (fewer than 5 markets, or too little verified record to cohort-rank). */
1720
+ grade?: "S" | "A" | "B" | "C" | "D" | "F";
1721
+ /** Hot-streak tier (trailing-7d cross-sectional percentile). Null when no recent activity. */
1722
+ streak_tier?: "hot" | "rising" | "neutral" | "cooling" | "cold";
1723
+ all_time_pnl_usd?: number | null;
1724
+ all_time_score?: number | null;
1725
+ last_synced?: string | null;
1726
+ /** Shape-only daily P&L sparkline across the window, derived from Polymarket's documented user-pnl cumulative curve (GET /v2/user-pnl) converted to per-day deltas. It conveys the trend of the curve only and is NOT guaranteed to sum to trending_pnl_usd, which is the canonical leaderboard total. */
1727
+ daily_pnl_series: {
1728
+ date: string;
1729
+ pnl_usd: number;
1730
+ }[];
1731
+ };
1732
+ /** Whether the described value or result set is complete for its stated contract. */
1733
+ export type TrustCompleteness = {
1734
+ status: "complete" | "partial" | "not_computed" | "not_applicable" | "unavailable";
1735
+ detail?: string | null;
1736
+ };
1737
+ /** Freshness metadata for a trust-critical value. This is separate from transport cache fields in ResponseMeta. */
1738
+ export type TrustFreshness = {
1739
+ status: "fresh" | "refreshing" | "stale" | "not_live" | "unknown" | "unavailable";
1740
+ as_of?: string | null;
1741
+ max_age_s?: number | null;
1742
+ };
1743
+ /** Shared source/freshness/reconciliation/completeness metadata for public API values that may be cached, stale, partial, computed, or provider-unavailable. Unavailable provider values must be represented with explicit metadata instead of fabricated zeros or empty arrays. */
1744
+ export type TrustMetadata = {
1745
+ source: TrustSource;
1746
+ freshness: TrustFreshness;
1747
+ reconciliation: TrustReconciliation;
1748
+ completeness: TrustCompleteness;
1749
+ };
1750
+ /** How provider-owned facts were reconciled with stored/read-model values. */
1751
+ export type TrustReconciliation = {
1752
+ status: "provider_backed" | "db_mirror" | "computed" | "partial" | "not_applicable" | "unavailable";
1753
+ detail?: string | null;
1754
+ };
1755
+ /** Source metadata for a trust-critical value. Providers and DB/read models own business truth; clients should not infer missing provider facts from titles, slugs, zeros, or empty arrays. */
1756
+ export type TrustSource = {
1757
+ kind: "provider" | "database" | "cache" | "computed" | "client_input" | "unavailable";
1758
+ /** Provider, table/read-model, cache, or service that owns the value. */
1759
+ owner: string;
1760
+ /** Provider field, DB column, or computed field name when applicable. */
1761
+ field?: string | null;
1762
+ };
1763
+ export type UpdateWebhookRequest = {
1764
+ name?: string;
1765
+ /** Replacement public HTTPS callback URL on the default port 443, validated and checked for uniqueness exactly like the create url. HTTPS scheme/host case, trailing DNS dots and port 443 normalize; path/query case is preserved. Changing it resets status to pending_verification and returns a new verification token; the new destination must pass the verification challenge before deliveries resume. */
1766
+ url?: string;
1767
+ event_types?: WebhookEventType[];
1768
+ enabled?: boolean;
1769
+ };
1770
+ export type Usage = {
1771
+ object: "usage";
1772
+ data: {
1773
+ rate_limit: {
1774
+ used: number;
1775
+ limit: number;
1776
+ remaining: number;
1777
+ reset_at: number;
1778
+ window_seconds: number;
1779
+ };
1780
+ /** UTC-day usage count. Current V1 has no daily hard cap, so limit and remaining are null rather than synthesized. */
1781
+ daily_usage: {
1782
+ used: number;
1783
+ limit: number | null;
1784
+ remaining: number | null;
1785
+ reset_at: number;
1786
+ window_seconds: number;
1787
+ };
1788
+ };
1789
+ meta: ResponseMeta;
1790
+ };
1791
+ export type VerifyWebhookRequest = {
1792
+ /** The one-time token returned on create or on a url change. It is necessary but not sufficient: the destination must also answer the signed webhook.verification challenge with a 2xx. */
1793
+ verification_token: string;
1794
+ };
1795
+ /** Owner-scoped view of one webhook delivery attempt. Deliberately omits the request body and the endpoint signing secret: a delivery log never re-exposes the payload or any secret material. */
1796
+ export type WebhookDelivery = {
1797
+ id: number;
1798
+ object: "webhook_delivery";
1799
+ /** Stable event id for this delivery; identical across retries of the same logical event. */
1800
+ event_id: string;
1801
+ event_type: WebhookEventType;
1802
+ /** Delivery lifecycle state (e.g. pending, delivered, dead_letter). */
1803
+ status: string;
1804
+ /** Number of delivery attempts made so far. */
1805
+ attempt_count: number;
1806
+ /** HTTP status code of the most recent delivery attempt. Omitted until a response (or transport error) has been recorded. */
1807
+ last_response_status?: number;
1808
+ /** Short description of the most recent delivery failure. Omitted when the last attempt succeeded or none has failed. */
1809
+ last_error?: string;
1810
+ /** When the delivery was first accepted by the destination. Omitted until a delivery succeeds. */
1811
+ delivered_at?: string;
1812
+ /** When the next delivery attempt is due, for a delivery whose status is pending or retry. null while an attempt is in flight (processing) and once the delivery is terminal (delivered or dead_letter). */
1813
+ next_attempt_at: string | null;
1814
+ created_at: string;
1815
+ };
1816
+ export type WebhookEndpoint = {
1817
+ id: number;
1818
+ object: "webhook";
1819
+ name: string;
1820
+ url: string;
1821
+ event_types: WebhookEventType[];
1822
+ status: WebhookStatus;
1823
+ verified_at?: string | null;
1824
+ verification_token_expires_at: string;
1825
+ failure_count: number;
1826
+ created_at: string;
1827
+ updated_at: string;
1828
+ retry_policy: WebhookRetryPolicy;
1829
+ /** Returned only on create or rotate-secret. */
1830
+ signing_secret?: string;
1831
+ verification?: WebhookVerification;
1832
+ };
1833
+ /** Self-describing entry in the webhook event catalog: the event type a subscriber lists in event_types, when it fires, the data payload shape, and whether it currently fires (active) or is reserved (dormant, subscribable but not yet delivered). Pro-only event types (whale_trades_inserted, wallet_grade_changed, insider_radar_flag_raised, smart_money_flow_detected) only deliver to API keys on an active Pro subscription. */
1834
+ export type WebhookEventDescriptor = {
1835
+ id: WebhookEventType;
1836
+ /** One-line description of when the event fires. */
1837
+ description: string;
1838
+ /** Short description of the data payload object's shape. */
1839
+ payload_shape: string;
1840
+ /** active: the event has a firing producer callsite. dormant: advertised and subscribable, but does not yet enqueue any delivery. */
1841
+ status: "active" | "dormant";
1842
+ };
1843
+ export type WebhookEventType = "whale_trades_inserted" | "live_sports_updated" | "whale_trader_synced" | "large_positions_updated" | "wallet_grade_changed" | "insider_radar_flag_raised" | "smart_money_flow_detected";
1844
+ export type WebhookRetryPolicy = {
1845
+ max_attempts: 8;
1846
+ terminal_status: "dead_letter";
1847
+ /** Total wait from a delivery's first failed attempt to its last retry: 60, 120, 240, 480, 960, 1920 and 3600 seconds. A delivery still failing after that is dead_letter. */
1848
+ retry_horizon_seconds: 7380;
1849
+ /** Consecutive failed attempts, across all of this endpoint's deliveries, after which the endpoint is disabled and its queued deliveries are dead-lettered. Any successful attempt resets the count. */
1850
+ disable_after_consecutive_failures: 8;
1851
+ };
1852
+ export type WebhookStatus = "pending_verification" | "active" | "disabled";
1853
+ export type WebhookVerification = {
1854
+ /** One-time verification token returned only on create or URL change. Pass it to POST /api/v1/webhooks/{id}/verify, which activates the endpoint only when the destination also answers the signed webhook.verification challenge with a 2xx. */
1855
+ token: string;
1856
+ expires_at: string;
1857
+ };
1858
+ export type WhaleTrade = {
1859
+ /** Prefixed ID (wt_...). */
1860
+ id: string;
1861
+ traded_at: string;
1862
+ size_usd: number;
1863
+ side: "BUY" | "SELL";
1864
+ /** Traded outcome label (e.g. "Yes"/"No"/team name), resolved provider-first from the trade's outcome_index against market_canonical (index 0 -> yes, 1 -> no). Distinct axis from side (BUY/SELL): side is the trade direction, outcome is which leg was traded. null for multi-outcome (outcome_index >= 2) or unsynced markets, and for a Polymarket trade recorded before 2026-04-02T00:00:00Z, whose stored outcome_index is not trusted (a defaulted 0 for about a third of those rows; the side is unknown, not defaulted). */
1865
+ outcome?: string | null;
1866
+ /** The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the traded outcome; null when unavailable (e.g. unsynced markets) and for a Polymarket trade recorded before 2026-04-02T00:00:00Z, where the traded side is unknown. */
1867
+ token_id?: string | null;
1868
+ price: number;
1869
+ /** Current 0.0–1.0 normalized signal score. This value can change as scoring context changes. */
1870
+ signal_score: number;
1871
+ /** 0.0–1.0 signal score written once when the trade row is inserted. Available for new rows after this field launched; legacy rows return null. If a trade is added later, its time-sensitive recorded score reflects that delay. */
1872
+ recorded_signal_score: number | null;
1873
+ /** Persisted live suspicion score from the scorer. Null when the row has no persisted score. */
1874
+ suspicion_score: number | null;
1875
+ /** Persisted scorer track. Null when a legacy row has no stored track label. */
1876
+ suspicion_track: "whale" | "fresh_conviction" | "sliced_position";
1877
+ /** This fill's size relative to its market: size_usd divided by the market's volume at the moment the trade was inserted. A $10,000 fill is 0.00005 of a $200M market and 0.125 of an $80,000 one, which size_usd alone cannot distinguish. Absent when the market carried no volume figure and on rows written before 2026-09-16; never 0 as a stand-in. Not capped at 1: a fill larger than the stored trailing volume is real, and that is the most significant case. */
1878
+ market_volume_share?: number;
1879
+ trader: {
1880
+ id: string;
1881
+ address: string;
1882
+ username?: string | null;
1883
+ grade?: string | null;
1884
+ };
1885
+ market: {
1886
+ id: string;
1887
+ condition_id: string;
1888
+ title: string;
1889
+ slug?: string | null;
1890
+ /** Provider-backed market_canonical category. */
1891
+ category?: string | null;
1892
+ };
1893
+ };
1894
+ export type WhaleTradeDetail = WhaleTrade & {
1895
+ counterparty_analysis: CounterpartyAnalysis;
1896
+ };
1897
+ export type WhaleTradeHistoryMeta = {
1898
+ /** Unique request ID (req_ prefix). */
1899
+ request_id: string;
1900
+ cached: boolean;
1901
+ /** Cache age in seconds, null if not cached. */
1902
+ cache_age_s?: number | null;
1903
+ source: {
1904
+ kind: "local_replay";
1905
+ table: "whale_alerts";
1906
+ provider_fetch_at_request_time: false;
1907
+ };
1908
+ completeness: {
1909
+ status: "best_effort";
1910
+ /** Explains that local replay completeness can vary by market and time window. */
1911
+ reason: string;
1912
+ };
1913
+ };
1914
+ /**
1915
+ * The `data` payload each operation answers with: what
1916
+ * `ApiClient.call<T>` resolves to, and the default `T` of every
1917
+ * convenience method.
1918
+ */
1919
+ export interface OperationData {
1920
+ batchGetMarketIntel: BatchMarketIntelItem[];
1921
+ batchGetTraders: BatchTraderItem[];
1922
+ createMcpJsonRpcResponse: {
1923
+ jsonrpc: "2.0";
1924
+ id: string | number | null;
1925
+ result?: Record<string, unknown>;
1926
+ error?: {
1927
+ code: number;
1928
+ message: string;
1929
+ };
1930
+ };
1931
+ createWebhook: WebhookEndpoint;
1932
+ deleteWebhook: WebhookEndpoint;
1933
+ exploreMarkets: ExploreEntry[];
1934
+ getAccountIdentity: {
1935
+ user_id: number;
1936
+ credential_id: number;
1937
+ credential_kind: "api_key" | "oauth_grant";
1938
+ /** Approved OAuth scopes; null for full developer-key access. */
1939
+ scopes: string[] | null;
1940
+ };
1941
+ getApiDiscovery: ApiDiscovery;
1942
+ getDailyReportSnapshot: ReportSnapshot;
1943
+ getEventReplaySince: EventReplayEvent[];
1944
+ getHealth: {
1945
+ status?: "ok" | "degraded" | "down" | "maintenance";
1946
+ db?: boolean;
1947
+ cache?: boolean;
1948
+ subsystems?: {
1949
+ /** Public-safe aggregate status for expected background job successful-completion heartbeats. Does not expose Redis keys, job names, raw errors, provider payloads, wallet addresses, or condition IDs. */
1950
+ background_jobs: {
1951
+ status: "ok" | "degraded" | "down" | "not_checked";
1952
+ checked: boolean;
1953
+ total: number;
1954
+ healthy: number;
1955
+ stale: number;
1956
+ missing: number;
1957
+ invalid: number;
1958
+ unconfigured: number;
1959
+ /** Heavy-periodic jobs that are stale/missing/invalid while the heavy executor is disabled (heavy_pipeline_control.executor_mode != 'active'), so this binary does not dispatch them. Observable but expected; they never drive status to 'down' (paused > 0 yields 'degraded'). */
1960
+ paused: number;
1961
+ };
1962
+ };
1963
+ };
1964
+ getInsiderRadarFlag: RadarFlag;
1965
+ getMarketCandles: MarketCandles;
1966
+ getMarketContextMarkdown: string;
1967
+ getMarketIntel: MarketIntel;
1968
+ getMarketSnapshot: MarketSnapshot;
1969
+ getMonthlyReportSnapshot: ReportSnapshot;
1970
+ getPickOfTheDay: PickOfTheDay;
1971
+ getPickOfTheDayArchive: PickOfTheDayArchive;
1972
+ getPlatforms: Platforms;
1973
+ getPositionTimeline: PositionTimelineEvent[];
1974
+ getPositionTimelineById: PositionTimelineEvent[];
1975
+ getReports: ReportSnapshot;
1976
+ getStream: string;
1977
+ getTrader: Trader;
1978
+ getTraderContext: TraderContext;
1979
+ getTraderContextMarkdown: string;
1980
+ getTraderExportSnapshot: TraderExportSnapshot;
1981
+ getTraderExportStatus: {
1982
+ job_id: number;
1983
+ status: "queued" | "running" | "ready" | "failed";
1984
+ format: "json" | "ndjson" | "csv";
1985
+ total_trades?: number | null;
1986
+ processed_trades?: number | null;
1987
+ file_size?: number | null;
1988
+ error?: string | null;
1989
+ };
1990
+ getTraderPnl: TraderPnl;
1991
+ getUsage: {
1992
+ rate_limit: {
1993
+ used: number;
1994
+ limit: number;
1995
+ remaining: number;
1996
+ reset_at: number;
1997
+ window_seconds: number;
1998
+ };
1999
+ /** UTC-day usage count. Current V1 has no daily hard cap, so limit and remaining are null rather than synthesized. */
2000
+ daily_usage: {
2001
+ used: number;
2002
+ limit: number | null;
2003
+ remaining: number | null;
2004
+ reset_at: number;
2005
+ window_seconds: number;
2006
+ };
2007
+ };
2008
+ getWebhook: WebhookEndpoint;
2009
+ getWeeklyReportSnapshot: ReportSnapshot;
2010
+ getWhaleTrade: WhaleTradeDetail;
2011
+ listInsiderRadar: RadarFlag[];
2012
+ listLargePositions: LargePosition[];
2013
+ listLeaderboard: LeaderboardEntry[];
2014
+ listPositions: Position[];
2015
+ listSharpMoneyFlows: SmartMoneyFlowMarket[];
2016
+ listSmartMoneyFlows: SmartMoneyFlowMarket[];
2017
+ listSportsEdgeObservations: SportsEdgeObservation[];
2018
+ listSportsEdgeSignals: SportsEdgeSignal[];
2019
+ listTrendingWallets: TrendingWallet[];
2020
+ listWebhookDeliveries: WebhookDelivery[];
2021
+ listWebhookEvents: WebhookEventDescriptor[];
2022
+ listWebhooks: WebhookEndpoint[];
2023
+ listWhaleTradeCounterpartyExecutions: CounterpartyAnalysis;
2024
+ listWhaleTradeCounterpartyMakers: CounterpartyMakerPage;
2025
+ listWhaleTradeHistory: WhaleTrade[];
2026
+ listWhaleTrades: WhaleTrade[];
2027
+ openMcpEventStream: string;
2028
+ redeliverWebhookDelivery: WebhookDelivery;
2029
+ rotateWebhookSecret: WebhookEndpoint;
2030
+ searchContent: ContentSearchResult[];
2031
+ searchMarkets: MarketSearchResult[];
2032
+ submitTraderExport: {
2033
+ job_id: number;
2034
+ status: "queued" | "running" | "ready" | "failed";
2035
+ format: "json" | "ndjson" | "csv";
2036
+ total_trades?: number | null;
2037
+ processed_trades?: number | null;
2038
+ file_size?: number | null;
2039
+ error?: string | null;
2040
+ };
2041
+ updateWebhook: WebhookEndpoint;
2042
+ verifyWebhook: WebhookEndpoint;
2043
+ }
2044
+ /** Each operation's documented query parameters. */
2045
+ export interface OperationQuery {
2046
+ batchGetMarketIntel: Record<string, never>;
2047
+ batchGetTraders: Record<string, never>;
2048
+ createMcpJsonRpcResponse: {
2049
+ /** Legacy API-key query parameter for exact /api/v1/mcp only. Every other protected V1 route rejects it. Prefer Authorization: Bearer <token> or the stdio package because URL secrets are easier to leak through logs and history. The retirement date is unknown until external URL-only client compatibility is checked. */
2050
+ token?: string;
2051
+ };
2052
+ createWebhook: Record<string, never>;
2053
+ deleteWebhook: Record<string, never>;
2054
+ exploreMarkets: {
2055
+ /** 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. */
2056
+ category?: string;
2057
+ /** Filter by market status. */
2058
+ status?: "active" | "closed" | "all";
2059
+ /** Filter by source platform. Explore is Polymarket-only; polymarket is the only supported value and the parameter is accepted for backward-compatibility but does not change the result set. */
2060
+ platform?: "polymarket";
2061
+ /** Sort order for the discovery feed. */
2062
+ sort?: "trending" | "hot" | "expiring" | "whales" | "volume" | "newest";
2063
+ /** Opaque pagination cursor from the previous response. */
2064
+ cursor?: string;
2065
+ /** Page size. */
2066
+ limit?: number;
2067
+ /** Keyword search against market titles. At most 64 characters before whitespace trimming. */
2068
+ q?: string;
2069
+ };
2070
+ getAccountIdentity: Record<string, never>;
2071
+ getApiDiscovery: Record<string, never>;
2072
+ getDailyReportSnapshot: {
2073
+ /** UTC report date in YYYY-MM-DD format. */
2074
+ date: string;
2075
+ };
2076
+ getEventReplaySince: {
2077
+ /** Opaque event replay cursor returned as next_cursor by a prior response. The cursor maps to whale_alerts.id and is valid across backend replicas. Omit to fetch the latest durable public suffix. */
2078
+ cursor?: string;
2079
+ /** Maximum durable public whale-trade events to return. */
2080
+ limit?: number;
2081
+ };
2082
+ getHealth: Record<string, never>;
2083
+ getInsiderRadarFlag: Record<string, never>;
2084
+ getMarketCandles: {
2085
+ /** Bucketing granularity. 1d aggregates by UTC calendar day, 1w by ISO week (Monday 00:00 UTC start). Defaults to 1d. */
2086
+ resolution?: "1d" | "1w";
2087
+ /** Exclusive lower bound as a unix timestamp in seconds; points at or before this timestamp are omitted (the underlying daily snapshot read filters bucket_start > from). Note: for resolution=1w a surviving mid-week point can yield a weekly candle whose t (Monday 00:00 UTC) precedes from. */
2088
+ from?: number;
2089
+ /** Inclusive upper bound as a unix timestamp in seconds; points after this timestamp are omitted. */
2090
+ to?: number;
2091
+ };
2092
+ getMarketContextMarkdown: Record<string, never>;
2093
+ getMarketIntel: {
2094
+ /** Lookback window for whale flow aggregation. */
2095
+ timeframe?: "1h" | "4h" | "24h" | "7d";
2096
+ };
2097
+ getMarketSnapshot: {
2098
+ /** Backward-compatible alias for expand. Repeatable: trust. */
2099
+ "expand[]"?: "trust"[];
2100
+ /** Include trust metadata for current_price and spread_bps. Repeatable: trust. */
2101
+ expand?: "trust"[];
2102
+ };
2103
+ getMonthlyReportSnapshot: {
2104
+ /** UTC report month in YYYY-MM format. */
2105
+ month: string;
2106
+ };
2107
+ getPickOfTheDay: Record<string, never>;
2108
+ getPickOfTheDayArchive: Record<string, never>;
2109
+ getPlatforms: Record<string, never>;
2110
+ getPositionTimeline: {
2111
+ /** Market condition_id. One timeline per (trader, market). */
2112
+ condition_id: string;
2113
+ /** Maximum number of timeline events to return. */
2114
+ limit?: number;
2115
+ /** Pagination cursor from previous response's next_cursor. */
2116
+ cursor?: string;
2117
+ };
2118
+ getPositionTimelineById: {
2119
+ /** Market condition_id. One timeline per (trader, market). */
2120
+ condition_id: string;
2121
+ /** Maximum number of timeline events to return. */
2122
+ limit?: number;
2123
+ /** Pagination cursor from previous response's next_cursor. */
2124
+ cursor?: string;
2125
+ };
2126
+ getReports: {
2127
+ /** Report granularity selector. */
2128
+ granularity: "daily" | "weekly" | "monthly";
2129
+ /** Period token for the granularity. daily: UTC date YYYY-MM-DD. weekly: ISO week YYYY-WW, or a from,to YYYY-MM-DD pair. monthly: UTC month YYYY-MM. */
2130
+ period: string;
2131
+ };
2132
+ getStream: {
2133
+ /** Query-string fallback for the Last-Event-ID resume cursor when the client cannot set the request header. Numeric cluster-shared sequence id; non-numeric or absent attaches live with no replay. A future or expired id emits resync. */
2134
+ last_event_id?: string;
2135
+ /** Alias for last_event_id. Numeric cluster-shared sequence id to resume after; non-numeric or absent attaches live with no replay. A future or expired id emits resync. */
2136
+ seq?: string;
2137
+ /** Optional per-connection subscribe-time filter. Comma-separated list of frame wire types (the SSE 'type' discriminator, e.g. WhaleTradesInserted,wallet_grade_changed); a frame passes only when its type is in the set. An unknown token returns HTTP 400 naming the offending value. An empty/all-whitespace value is treated as absent (no constraint). Applied to BOTH the replay window and live frames, and always AFTER the per-subscriber privacy gate, so it can never widen visibility beyond what the key may already see. Combines with condition_id and min_grade as a logical AND; an absent param adds no constraint. */
2138
+ event?: string;
2139
+ /** 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. */
2140
+ condition_id?: string;
2141
+ /** Optional per-connection subscribe-time filter. A frame passes only when it carries a grade field whose grade is better-or-equal to this minimum (S is best). Frames that carry no grade field (every frame except wallet_grade_changed) are EXCLUDED while this is set. An invalid grade returns HTTP 400. Combines with event and condition_id as a logical AND; an absent param adds no constraint. */
2142
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2143
+ };
2144
+ getTrader: {
2145
+ /** Backward-compatible alias for expand. Repeatable: strategy, categories, quant_metrics, trust. */
2146
+ "expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
2147
+ /** Include heavy fields and trust metadata. Repeatable: strategy, categories, quant_metrics, trust. */
2148
+ expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
2149
+ };
2150
+ getTraderContext: Record<string, never>;
2151
+ getTraderContextMarkdown: Record<string, never>;
2152
+ getTraderExportSnapshot: Record<string, never>;
2153
+ getTraderExportStatus: {
2154
+ /** Export job id returned by the submit route. */
2155
+ job_id: number;
2156
+ };
2157
+ getTraderPnl: Record<string, never>;
2158
+ getUsage: Record<string, never>;
2159
+ getWebhook: Record<string, never>;
2160
+ getWeeklyReportSnapshot: {
2161
+ /** UTC source-range start in YYYY-MM-DD format; required with to. */
2162
+ from?: string;
2163
+ /** UTC source-range end in YYYY-MM-DD format; required with from. */
2164
+ to?: string;
2165
+ /** ISO week selector in YYYY-WW format; alternative to from/to. */
2166
+ week?: string;
2167
+ };
2168
+ getWhaleTrade: Record<string, never>;
2169
+ listInsiderRadar: {
2170
+ /** Maximum number of radar flags to return. */
2171
+ limit?: number;
2172
+ /** Pagination cursor from previous response. */
2173
+ cursor?: string;
2174
+ /** Minimum suspicion score (0-100). The live flag floor of 60 also applies. */
2175
+ min_suspicion?: number;
2176
+ /** Compatible filter. flag selects live threshold crossings. watch returns no rows because no live watch policy exists. */
2177
+ severity?: "flag" | "watch";
2178
+ };
2179
+ listLargePositions: {
2180
+ /** Maximum number of large positions to return. */
2181
+ limit?: number;
2182
+ /** Opaque pagination cursor from a previous response. */
2183
+ cursor?: string;
2184
+ /** Minimum position value in USD. */
2185
+ min_size?: number;
2186
+ /** 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. */
2187
+ category?: string;
2188
+ /** Minimum trader grade. */
2189
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2190
+ /** Scope to one market. Accepts the raw provider condition_id or the mkt_-prefixed market id (round-trips a value from a list response). Polymarket-only; an unknown id returns []. */
2191
+ condition_id?: string;
2192
+ };
2193
+ listLeaderboard: {
2194
+ /** Maximum number of ranked traders to return. */
2195
+ limit?: number;
2196
+ /** Opaque lbv1_ pagination cursor from a prior response. It binds the finite score/address boundary to the committed leaderboard generation and the effective category/strategy filters; legacy, malformed, non-finite, and unsupported-version cursors are rejected. */
2197
+ cursor?: string;
2198
+ /** Filter by category. Values are matched to canonical category buckets: political variants (Elections, Global Politics, U.S. Politics, ...) fold into Politics, Geopolitics stays distinct, Culture/Entertainment map to Pop Culture, Science maps to Science & Tech, and Finance/Business map to Stocks. Mapped buckets are case-insensitive; passthrough categories (Crypto, NBA, and the sports leagues) match case-sensitively against the provider-native bucket key, so use exact casing (e.g. Crypto, NBA). */
2199
+ category?: string;
2200
+ /** Filter by ML-detected strategy type. Values come from backend/crates/analytics/src/trader_analysis/classification/decision_tree.rs and are matched exactly against ml_trader_category.primary_type. Values outside the declared enum return HTTP 400. */
2201
+ strategy?: "accumulator" | "algo_trader" | "arbitrageur" | "directional" | "event_driven" | "market_maker" | "momentum" | "scalper" | "speculator" | "swing_trader";
2202
+ };
2203
+ listPositions: {
2204
+ /** Maximum number of current positions to return. */
2205
+ limit?: number;
2206
+ /** Pagination cursor from previous response's next_cursor. */
2207
+ cursor?: string;
2208
+ /** Minimum current position value in USD. */
2209
+ min_size?: number;
2210
+ /** Exact match against provider-backed market_canonical.category. */
2211
+ category?: string;
2212
+ /** Minimum trader grade allowlist. `A` matches S and A; `B` matches S, A, B; etc. */
2213
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2214
+ /** Filter by the binary outcome side. `yes` maps to outcome_index=0, `no` to outcome_index=1. */
2215
+ side?: "yes" | "no";
2216
+ };
2217
+ listSharpMoneyFlows: {
2218
+ /** Lookback window for grade-filtered whale flow aggregation. */
2219
+ timeframe?: "1h" | "4h" | "24h" | "7d";
2220
+ /** Page size. */
2221
+ limit?: number;
2222
+ /** Opaque cursor from previous response's next_cursor. Encodes the first-page as_of timestamp plus the last row's absolute net flow and condition_id. */
2223
+ cursor?: string;
2224
+ /** 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. */
2225
+ category?: string;
2226
+ /** Filter by source platform. all is a request-side no-op. */
2227
+ platform?: "polymarket" | "all";
2228
+ /** Minimum latest trader grade included in the flow. Default B means S/A/B only; unranked traders are excluded. */
2229
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2230
+ /** Optional post-aggregate flow direction filter. */
2231
+ direction?: "YES" | "NO";
2232
+ };
2233
+ listSmartMoneyFlows: {
2234
+ /** Lookback window for grade-filtered whale flow aggregation. */
2235
+ timeframe?: "1h" | "4h" | "24h" | "7d";
2236
+ /** Page size. */
2237
+ limit?: number;
2238
+ /** Opaque cursor from previous response's next_cursor. Encodes the first-page as_of timestamp plus the last row's absolute net flow and condition_id. */
2239
+ cursor?: string;
2240
+ /** 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. */
2241
+ category?: string;
2242
+ /** Filter by source platform. all is a request-side no-op. */
2243
+ platform?: "polymarket" | "all";
2244
+ /** Minimum latest trader grade included in the flow. Default B means S/A/B only; unranked traders are excluded. */
2245
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2246
+ /** Optional post-aggregate flow direction filter. */
2247
+ direction?: "YES" | "NO";
2248
+ };
2249
+ listSportsEdgeObservations: {
2250
+ /** Observation cohort. wider_holder measures pre-game holder piles outside the funded route's exact raw signals admission. in_play admits only provider-confirmed live games and excludes stale or unavailable provider live-board, holder, or directional evidence. emerging_pile is a post-compute wider_holder projection for finite sharp_pct in [0.75, 0.85) with holder_scan_complete=true and a kickoff after its pinned projection cutoff; it overlaps wider_holder, is not an independent denominator, and is not arrival history. */
2251
+ cohort: "wider_holder" | "in_play" | "emerging_pile";
2252
+ /** Optional canonical sport bucket. Omitted or blank selects all registered sports. Raw provider categories resolve through the canonical taxonomy, including table-tennis or table tennis to Table Tennis and pickleball to Pickleball; a non-sport category returns an empty list. */
2253
+ category?: string;
2254
+ /** Page size. */
2255
+ limit?: number;
2256
+ /** Server-authenticated opaque seo_v2_ cursor from next_cursor. Pins snapshot_as_of, cohort, rank, and condition_id; pre-deploy unsigned seo_ cursors are rejected, so clients must request the first page after this contract ships; emerging_pile cursors also pin the first-page projection_now cutoff so kickoff filtering cannot renumber continuation pages. Client edits fail closed; it cannot cross cohorts; a refreshed snapshot invalidates it with 400. */
2257
+ cursor?: string;
2258
+ };
2259
+ listSportsEdgeSignals: {
2260
+ /** Optional canonical sport bucket filter (e.g. Basketball, Tennis, Soccer). A raw provider value (NBA) resolves to its canonical bucket. A non-sport category returns an empty list. */
2261
+ category?: string;
2262
+ /** Page size. */
2263
+ limit?: number;
2264
+ /** Opaque cursor from a previous response's next_cursor. Encodes the snapshot anchor plus the last row's directional_rank_score, conviction_score, smart_score and condition_id. A cursor from an expired snapshot returns 400. */
2265
+ cursor?: string;
2266
+ /** Kickoff ceiling in hours from now; the floor is now (only games not yet started). Clamped to 1..48. */
2267
+ horizon_hours?: number;
2268
+ /** Minimum trader grade required on the piled side. Only S, A, B are accepted (the piled-side grade distribution is S/A/B only; C, D, F return 400). Default B means at least one S/A/B holder is piled; S requires an S holder, A requires an S or A holder. */
2269
+ min_grade?: "S" | "A" | "B";
2270
+ };
2271
+ listTrendingWallets: {
2272
+ /** Polymarket's weekly leaderboard caps the ranked set at 50 wallets; requests above 50 still return at most 50. */
2273
+ limit?: number;
2274
+ /** Opaque pagination cursor from a previous response. */
2275
+ cursor?: string;
2276
+ /** Trailing window. */
2277
+ window?: "7d" | "30d";
2278
+ };
2279
+ listWebhookDeliveries: {
2280
+ /** Opaque pagination cursor returned as next_cursor by a prior response. Omit to fetch the newest page. */
2281
+ cursor?: string;
2282
+ /** Maximum delivery rows to return per page. */
2283
+ limit?: number;
2284
+ };
2285
+ listWebhookEvents: Record<string, never>;
2286
+ listWebhooks: Record<string, never>;
2287
+ listWhaleTradeCounterpartyExecutions: {
2288
+ /** Counterparty snapshot ID from the whale trade detail response. */
2289
+ snapshot_id: string;
2290
+ /** Opaque cursor from the previous response's next_cursor. */
2291
+ cursor?: string;
2292
+ /** Maximum number of counterparty execution rows to return. */
2293
+ limit?: number;
2294
+ };
2295
+ listWhaleTradeCounterpartyMakers: {
2296
+ /** Counterparty snapshot ID from the whale trade detail response. */
2297
+ snapshot_id: string;
2298
+ /** Opaque cursor from the previous response's next_cursor. */
2299
+ cursor?: string;
2300
+ /** Maximum number of maker rows to return. */
2301
+ limit?: number;
2302
+ };
2303
+ listWhaleTradeHistory: {
2304
+ /** Maximum number of historical large trades to return. */
2305
+ limit?: number;
2306
+ /** Pagination cursor from previous response's next_cursor. Prefix: wth_. URL-encode when replaying as a query parameter. */
2307
+ cursor?: string;
2308
+ /** Minimum trade size in USD. */
2309
+ min_size?: number;
2310
+ /** Exact raw provider condition_id. Unknown markets return an empty list. */
2311
+ condition_id?: string;
2312
+ /** Trader wallet address, timestamp-suffixed wallet alias, or username resolved against the traders table. Unknown traders return an empty list. */
2313
+ trader?: string;
2314
+ /** 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. */
2315
+ category?: string;
2316
+ /** Minimum trader grade. */
2317
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2318
+ /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
2319
+ suspicious_only?: boolean;
2320
+ /** Filter by whale_alerts.platform. all is equivalent to omitted. */
2321
+ platform?: "polymarket" | "all";
2322
+ /** Inclusive RFC3339 lower bound on whale_alerts.traded_at. */
2323
+ from?: string;
2324
+ /** Exclusive RFC3339 upper bound on whale_alerts.traded_at. Must be after from when both are present. */
2325
+ to?: string;
2326
+ };
2327
+ listWhaleTrades: {
2328
+ /** Maximum number of recent large trades to return. */
2329
+ limit?: number;
2330
+ /** Pagination cursor from previous response's next_cursor. */
2331
+ cursor?: string;
2332
+ /** Minimum trade size in USD. */
2333
+ min_size?: number;
2334
+ /** 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. */
2335
+ category?: string;
2336
+ /** Minimum trader grade. */
2337
+ min_grade?: "S" | "A" | "B" | "C" | "D" | "F";
2338
+ /** When true, return only rows with persisted suspicion_score >= 60. The filter is applied before SQL-backed limit + 1 pagination. */
2339
+ suspicious_only?: boolean;
2340
+ };
2341
+ openMcpEventStream: {
2342
+ /** Legacy API-key query parameter for exact /api/v1/mcp only. Every other protected V1 route rejects it. Same contract as POST. */
2343
+ token?: string;
2344
+ };
2345
+ redeliverWebhookDelivery: Record<string, never>;
2346
+ rotateWebhookSecret: Record<string, never>;
2347
+ searchContent: {
2348
+ /** Search query. Must be 1-256 characters before whitespace trimming and non-empty after trimming. */
2349
+ q: string;
2350
+ /** Maximum content items to return. */
2351
+ limit?: number;
2352
+ };
2353
+ searchMarkets: {
2354
+ /** Search query. Must be 1-512 characters before whitespace trimming and non-empty after trimming. */
2355
+ q: string;
2356
+ /** Maximum number of matching markets to return. */
2357
+ limit?: number;
2358
+ /** Pagination cursor from previous response's next_cursor. */
2359
+ cursor?: string;
2360
+ /** Filter by market status. */
2361
+ status?: "active" | "closed" | "all";
2362
+ /** Filter by category. */
2363
+ category?: string;
2364
+ };
2365
+ submitTraderExport: {
2366
+ /** Output serialization. json = full envelope document (default); ndjson = full envelope as line 1 then one trade object per line; csv = flat trades rows only. */
2367
+ format?: "json" | "ndjson" | "csv";
2368
+ };
2369
+ updateWebhook: Record<string, never>;
2370
+ verifyWebhook: Record<string, never>;
2371
+ }
2372
+ //# sourceMappingURL=schema.d.ts.map