@0xinsider/sdk 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/data-quality.d.ts +10 -5
- package/dist/data-quality.d.ts.map +1 -1
- package/dist/data-quality.js +2 -2
- package/dist/data-quality.js.map +1 -1
- package/dist/errors.d.ts +21 -9
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +25 -7
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/provenance.js +2 -2
- package/dist/schema.d.ts +67 -25
- package/dist/schema.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/schema.d.ts
CHANGED
|
@@ -77,8 +77,10 @@ export type ApiError = {
|
|
|
77
77
|
/** The recommended next request instant (RFC3339), always in the future. Present on every retryable error: `pick_not_released`, `rate_limited`, `rate_limit_unavailable`, and `read_model_warming`. Omitted otherwise. The absolute twin of `Retry-After`; prefer the header for the sleep duration. For `pick_not_released`, the earliest of the next scheduled release, the next automatic selector attempt, the operating-window start, or about 60 seconds. See that response. */
|
|
78
78
|
retry_at?: string;
|
|
79
79
|
freshness?: FreshnessFailure;
|
|
80
|
-
/**
|
|
81
|
-
|
|
80
|
+
/** Where a person clears this 402 (#32592): pays the overdue invoice (reason payment_overdue) or reactivates the plan (reason subscription_inactive). Present on every 402 subscription_required, omitted on every other error. The message names the same URL; link this field instead of parsing the message. */
|
|
81
|
+
billing_url?: string;
|
|
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 not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. payment_overdue (402 subscription_required, #32592): the key is valid and the account still has its plan, but its latest subscription invoice is unpaid (Stripe past_due or unpaid), so paid access is paused; permanent until a person pays at billing_url (https://0xinsider.com/billing) -- stop retrying on a schedule and surface the link. The key works again the moment the invoice is paid. GET /api/v1/me and GET /api/v1/usage keep answering. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. cold_read_limited (429 rate_limited, #28752): the account has used its share of cold reads on GET /api/v1/market/{condition_id}/holders, requests for a market whose roster is not cached, each of which walks Polymarket (6 a minute, in bursts of up to 400); not the per-minute window, so a cached market still answers, and the next cold read is admitted at Retry-After. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
|
|
83
|
+
reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "payment_overdue" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "cold_read_limited" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
|
|
82
84
|
};
|
|
83
85
|
meta: ResponseMeta;
|
|
84
86
|
};
|
|
@@ -91,8 +93,10 @@ export type ApiErrorBody = {
|
|
|
91
93
|
/** The recommended next retry instant (RFC3339). Present on every retryable error (reason=pick_not_released, code=rate_limited including reason=monthly_quota_exceeded, code=rate_limit_unavailable, reason=read_model_warming) and omitted otherwise. Always in the future. For pick_not_released, the recommendation is advisory and can change before a pick becomes available. Schedule the next request from the returned value instead of inferring a release schedule or polling. Prefer Retry-After for the duration because it is immune to client clock skew. */
|
|
92
94
|
retry_at?: string;
|
|
93
95
|
freshness?: FreshnessFailure;
|
|
94
|
-
/**
|
|
95
|
-
|
|
96
|
+
/** Where a person clears this 402 (#32592): pays the overdue invoice (reason payment_overdue) or reactivates the plan (reason subscription_inactive). Present on every 402 subscription_required, omitted on every other error. The message names the same URL; link this field instead of parsing the message. */
|
|
97
|
+
billing_url?: string;
|
|
98
|
+
/** ADDITIVE (#7209). The specific, actionable cause behind `code`, when there is one more specific than the code itself. `code` keeps its published values, so existing clients are unaffected; new clients branch on `reason`. Omitted when the code already says everything we know. pick_not_released: no Pick of the Day is published for the current product day; schedule one request against retry_at instead of polling. unknown_endpoint: the PATH is not a route on this API -- read GET /api/v1, do not retry. trader_not_tracked: the wallet is real and the URL is right, but the trader is not on the warm sync tier (the wallets we sync most often) -- stop asking for this wallet. market_out_of_scope (404 not_found, #27303): the market or event is real and the URL is right, but 0xinsider serves sports and esports markets only -- stop asking for this market; neither a retry nor another URL for it can succeed. cursor_expired: pagination went stale mid-walk -- re-request the first page and continue. read_model_warming: the requested endpoint cannot serve its read model yet; exact causes are endpoint-specific and can include a cold or contended refresh or a dependency that prevented refresh. database_unavailable: the API's database or its connection pool is temporarily unreachable (a connection-class failure, not a query fault); code stays rate_limit_unavailable, nothing is rate-limited, retry after Retry-After / retry_at. idempotency_in_progress: retain the exact Idempotency-Key and request body, then retry shortly. webhook_delivery_in_progress: retry the URL or signing-secret configuration change after the destination's active request completes. request_accounting_unavailable: accounting capacity is unavailable before the handler executes; retry after Retry-After / retry_at. sandbox_api_key: the credential is a sandbox key (oxi_sk_test_) from POST /api/v1/agents/register, which only the sandbox server accepts -- call the sandbox base URL with it, or get a live key or OAuth access token; do not retry it here. api_key_in_query: the key was sent as a ?token= query parameter, which no route reads because URLs land in logs and history; the key itself was not checked -- resend it as Authorization: Bearer. subscription_inactive: the key is valid but the account's Pro subscription has lapsed (402 subscription_required); permanent until a person reactivates at https://0xinsider.com/billing, which the message names -- stop retrying on a schedule and surface the link. The key owner is emailed once per lapse. payment_overdue (402 subscription_required, #32592): the key is valid and the account still has its plan, but its latest subscription invoice is unpaid (Stripe past_due or unpaid), so paid access is paused; permanent until a person pays at billing_url (https://0xinsider.com/billing) -- stop retrying on a schedule and surface the link. The key works again the moment the invoice is paid. GET /api/v1/me and GET /api/v1/usage keep answering. monthly_quota_exceeded: the account has used the requests its plan includes for the UTC calendar month (429 rate_limited); retry_at and Retry-After name the first of next month, the only retry that can succeed, and the message names https://0xinsider.com/developers, where pay as you go for requests over the quota is turned on. The X-Monthly-Quota-Limit, X-Monthly-Quota-Remaining and X-Monthly-Quota-Reset headers on every authenticated response say how close the account is. invalid_query, invalid_path, invalid_body (400 bad_request, #16146): a query parameter, a path segment or the JSON body did not parse or does not fit the route's schema, so no handler ran; param names the field when the parser named one (a query key, a path segment, a JSON path such as traders[0], or body); fix the request, never retry it as sent. unsupported_media_type (415 bad_request, param content-type): send the body with Content-Type: application/json. payload_too_large (413 bad_request, param body): the body is over 1048576 bytes. method_not_allowed (405 bad_request): the path is a route but not with this method; the Allow header names the methods it serves. ip_rate_limited (429 rate_limited, #16380): the per-address budget every caller behind one IP shares, counted before authentication, is spent; not the key's own window, and the RateLimit-* headers describe that bucket. ip_throttled (429 rate_limited): the address is in a cooldown after sustained over-limit traffic; Retry-After is minutes to days, and a request before it does not shorten the cooldown. cold_read_limited (429 rate_limited, #28752): the account has used its share of cold reads on GET /api/v1/market/{condition_id}/holders, requests for a market whose roster is not cached, each of which walks Polymarket (6 a minute, in bursts of up to 400); not the per-minute window, so a cached market still answers, and the next cold read is admitted at Retry-After. max_plan_required (403 forbidden, #23085): the key is valid and its account is on Pro, but the route is part of Max (GET /api/v1/edge-hunter); every Pro route keeps working with the same key, so do not disable it. The message names https://0xinsider.com/pricing, where the account upgrades; a retry never clears it. endpoint_retired (410): this legacy sports endpoint no longer serves data. Migrate to GET /api/v1/edge-hunter; retrying the retired path cannot succeed. */
|
|
99
|
+
reason?: "cursor_expired" | "unknown_endpoint" | "pick_not_released" | "trader_not_tracked" | "market_out_of_scope" | "read_model_warming" | "database_unavailable" | "request_accounting_unavailable" | "idempotency_in_progress" | "webhook_delivery_in_progress" | "webhook_secret_rotation_not_prepared" | "webhook_secret_rotation_overlap_active" | "sandbox_api_key" | "api_key_in_query" | "subscription_inactive" | "payment_overdue" | "monthly_quota_exceeded" | "invalid_query" | "unknown_query_parameter" | "invalid_path" | "invalid_body" | "unsupported_media_type" | "payload_too_large" | "method_not_allowed" | "ip_rate_limited" | "ip_throttled" | "cold_read_limited" | "export_expired" | "freshness_ceiling_unsatisfied" | "max_plan_required" | "endpoint_retired";
|
|
96
100
|
};
|
|
97
101
|
export type BatchGameHoldersItem = {
|
|
98
102
|
/** Zero-based request index. Duplicate inputs keep separate result rows. */
|
|
@@ -473,10 +477,10 @@ export type CreateWebhookVerificationAttemptRequest = {
|
|
|
473
477
|
/** The original one-time token returned by webhook creation or a URL change. Sent only in the request body and signed receiver challenge. */
|
|
474
478
|
verification_token: string;
|
|
475
479
|
};
|
|
476
|
-
/** Compact data age and coverage for a response body, always present on the operations that publish it. Read status and as_of to decide whether to use the body at all, and field_groups to see which part is weak. Everything here comes from stored observation clocks, so a cached body reports the same ages a freshly computed one does: meta.cached and meta.cache_age_s stay the only transport-time facts and neither makes this block newer. The per-field audit object is still available through expand=trust; this is the default summary of the same question. */
|
|
480
|
+
/** Compact data age and coverage for a response body, always present on the operations that publish it. Read status and as_of to decide whether to use the body at all, and field_groups to see which part is weak. Everything here comes from stored observation clocks, and each clocked group is judged against its writer's budget when the body is served, so a cached body reports the same ages and verdicts a freshly computed one does: meta.cached and meta.cache_age_s stay the only transport-time facts and neither makes this block newer. The per-field audit object is still available through expand=trust; this is the default summary of the same question. */
|
|
477
481
|
export type DataQuality = {
|
|
478
|
-
/** fresh when every group is fresh, unavailable when every group is unavailable, and partial in every other case. */
|
|
479
|
-
status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
482
|
+
/** fresh when every group is fresh, unavailable when every group is unavailable, stale when every group is fresh or stale and at least one is stale, and partial in every other case. */
|
|
483
|
+
status: "fresh" | "stale" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
480
484
|
/** The oldest as_of among the groups that carry one: the age of the weakest clock this body rests on. Omitted when no group carries a clock. */
|
|
481
485
|
as_of?: string;
|
|
482
486
|
/** One entry per field group. Entries may be added in later releases, so match on group rather than on position or length. */
|
|
@@ -488,12 +492,14 @@ export type DataQualityGroup = {
|
|
|
488
492
|
group: string;
|
|
489
493
|
/** The table and column that write this group, named so the verdict can be audited (for example trader_rankings.computed_at). */
|
|
490
494
|
owner: string;
|
|
491
|
-
/** fresh: served,
|
|
492
|
-
status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
495
|
+
/** fresh: served, as_of carries this group's real observation or computation clock, and that clock is no older than max_age_s when the group carries one. stale: served and clocked, but as_of is older than max_age_s, so the writer has missed a refresh its schedule promises. partial: some of the group's fields are served and some are missing. unknown: served, and this read has no clock for it, so no age may be inferred. untracked: 0xinsider does not track this group for this subject, by design. unavailable: the group could not be served. New values may be added; treat one you do not recognize as unknown. Neither fresh nor stale is a tolerance for your use: compare as_of against your own. */
|
|
496
|
+
status: "fresh" | "stale" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
493
497
|
/** When this group's values were observed or computed. Omitted whenever the read cannot measure it, and never filled with the serialization time, the cache time, or another group's clock. */
|
|
494
498
|
as_of?: string;
|
|
495
499
|
/** Why the status is not fresh. Omitted when it is. */
|
|
496
500
|
reason?: string;
|
|
501
|
+
/** The longest gap in seconds this group's writer leaves between refreshes on its schedule: the age past which the group reads stale instead of fresh. Omitted when the writer keeps no schedule its clock could fall behind (a clock stamped once, only on a change, or when a reader asks), and such a group is never stale. It is the writer's promise, not a tolerance for your use. */
|
|
502
|
+
max_age_s?: number;
|
|
497
503
|
};
|
|
498
504
|
/** The full Max-only Edge Hunter board. Defaults cover all sports and esports with B grade floor, 48-hour horizon and at most 30 rows; common selections, legacy category, min_grade and limit narrow that projection. No pagination or ETag. Rows add frozen market_context discovery metadata. */
|
|
499
505
|
export type EdgeHunterBoard = {
|
|
@@ -589,7 +595,7 @@ export type EdgeHunterObservation = {
|
|
|
589
595
|
/** 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. */
|
|
590
596
|
cohort: "wider_holder" | "in_play" | "emerging_pile";
|
|
591
597
|
/** Which evaluation place in its sport the row took this refresh. most_held: a wider_holder place for up to 8 markets per sport kicking off within 24 hours, most graded holders first, kept until kickoff while the holder page still shows a card or could not be read; also every in_play row, whose places go most graded holders first. soonest_kickoff: a wider_holder place among the sport's 8 soonest kickoffs, which is not kept. emerging_pile rows carry their source wider_holder row's value. Filter on most_held to keep the most-held selection. most_held_48h: every row of an admission=most_held_48h response, which is that opt-in selection (up to 8 markets per sport within 48 hours, most graded holders first, recomputed every refresh), including a market a default place also evaluates; it never appears on a default response. */
|
|
592
|
-
admitted_by: "most_held" | "soonest_kickoff" | "most_held_48h";
|
|
598
|
+
admitted_by: "most_held" | "soonest_kickoff" | "most_held_48h" | "most_held_48h_by_type";
|
|
593
599
|
/** Always true. This row must not be routed to an order executor. */
|
|
594
600
|
observation_only: true;
|
|
595
601
|
/**
|
|
@@ -672,7 +678,7 @@ export type EdgeHunterObservationDeparture = {
|
|
|
672
678
|
/** Canonical sport bucket the departed card carried. */
|
|
673
679
|
category: "Basketball" | "Football" | "Baseball" | "Hockey" | "MMA" | "Boxing" | "Soccer" | "Cricket" | "Golf" | "Tennis" | "Esports" | "Racing" | "Table Tennis" | "Pickleball";
|
|
674
680
|
/** The departed card's admitted_by: most_held_48h on an admission=most_held_48h response. */
|
|
675
|
-
admitted_by: "most_held" | "soonest_kickoff" | "most_held_48h";
|
|
681
|
+
admitted_by: "most_held" | "soonest_kickoff" | "most_held_48h" | "most_held_48h_by_type";
|
|
676
682
|
/** Kickoff the departed card carried, in UTC. The entry leaves the list once it passes. */
|
|
677
683
|
game_start_time: string;
|
|
678
684
|
/** The departed card's observed_at: when its last evaluation finished. */
|
|
@@ -702,7 +708,7 @@ export type EdgeHunterObservationsResponse = {
|
|
|
702
708
|
/** Normalized axes requested with a selector or category; omitted on an unselected default read. */
|
|
703
709
|
selection?: EdgeHunterSelection;
|
|
704
710
|
/** Echoes the opt-in admission rule a request named; omitted on a default read. When present, data, funnel, coverage, degraded and degradation_reasons describe that selection, not the default one. */
|
|
705
|
-
admission?: "most_held_48h";
|
|
711
|
+
admission?: "most_held_48h" | "most_held_48h_by_type";
|
|
706
712
|
/** cohort=wider_holder only, for the default selection and for admission=most_held_48h: markets that had a wider_holder card in an earlier snapshot of the same selection, have none in this one, and have not kicked off. Newest departed_at first. An entry stays until the game_start_time it carries passes, and leaves as soon as the market has a card again; while it stays, its reason changes only while it reports an unfinished read or when view=signals starts or stops listing the market (see reason), and a later departure of the same market is a new entry. Filtered by the same category and selectors as data, and identical on every page of one snapshot. At most 336 entries; when more are open, the oldest departures leave first. An empty array means no card of this selection is departed. Omitted on in_play and emerging_pile, and on a snapshot that could not establish its departures, never reported as an empty array. Tracking that restarts after its record is lost starts empty. */
|
|
707
713
|
departures?: EdgeHunterObservationDeparture[];
|
|
708
714
|
/** The ranked_at of the view=signals snapshot whose listed markets this snapshot excluded from wider_holder as primary_slate_candidate. The refresh that computed this snapshot read it as it started, so it can be one refresh older than the view=signals snapshot a reader sees at the same moment. null when no view=signals snapshot could be read: that refresh excluded no market, and the funnel counts no primary_slate_candidate. Omitted on an unmappable legacy category, which reads no generation. */
|
|
@@ -1233,8 +1239,8 @@ export type FreshnessFailure = {
|
|
|
1233
1239
|
actual_age_s?: number;
|
|
1234
1240
|
/** The oldest stored data-quality clock used to calculate actual_age_s, when one is available. */
|
|
1235
1241
|
as_of?: string;
|
|
1236
|
-
/** The trader body's whole-response data-quality status. Only fresh can satisfy max_age_s. */
|
|
1237
|
-
data_quality_status: "fresh" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
1242
|
+
/** The trader body's whole-response data-quality status. Only fresh or stale can satisfy max_age_s: the ceiling replaces each writer's own budget, so a stale body inside it is answered. */
|
|
1243
|
+
data_quality_status: "fresh" | "stale" | "partial" | "unknown" | "untracked" | "unavailable";
|
|
1238
1244
|
};
|
|
1239
1245
|
/** One sports or esports game: both sides, its schedule, provider status, its winner markets (the moneyline, or the soccer 1X2 legs) with their available provider moneyline price states and liquidity, and the game's traded volume. The event's other markets are on GET /api/v1/games/{event_slug}/markets. Assembled from the same provider-first live and upcoming projections the site's boards use, with no request-time provider fan-out. */
|
|
1240
1246
|
export type Game = {
|
|
@@ -1267,6 +1273,8 @@ export type Game = {
|
|
|
1267
1273
|
sharp_money?: GameSharpMoney;
|
|
1268
1274
|
/** The game's traded volume, the figure the sports board carries for it, with its source, basis, unit and observation clock. A client can rank or filter games by volume.value. Omitted when the board carries no volume for the game, and on a finished game read from its stored record (freshness.source stored); never 0 in place of a missing figure. */
|
|
1269
1275
|
volume?: GameVolume;
|
|
1276
|
+
/** A tennis game's tournament edition: its tier, city and country, venue time zone and official dates, from 0xinsider's reviewed registry, the same facts the game's page states. Omitted outside tennis, on a finished game read from its stored record (freshness.source stored), and when the registry holds no single edition for the game's competition label, players' tour and kickoff; never a guessed value. */
|
|
1277
|
+
tournament?: GameTournament;
|
|
1270
1278
|
};
|
|
1271
1279
|
/** One side of the game. */
|
|
1272
1280
|
export type GameCompetitor = {
|
|
@@ -1490,6 +1498,38 @@ export type GameStatus = {
|
|
|
1490
1498
|
/** Whether the game is over. Always present. */
|
|
1491
1499
|
ended: boolean;
|
|
1492
1500
|
};
|
|
1501
|
+
/** The tennis tournament edition a game belongs to, curated from official ATP, WTA and ITF pages (source_urls), never from Polymarket, which supplies the competition label and tour only. Selected by the game's provider competition label, the one tour both players carry, and the kickoff's day at the venue. A fact no official page states is omitted. */
|
|
1502
|
+
export type GameTournament = {
|
|
1503
|
+
/** The provider competition label that selected this edition, verbatim, for example "Erste Bank Open, Qualification". */
|
|
1504
|
+
label: string;
|
|
1505
|
+
/** The edition's tour. */
|
|
1506
|
+
tour: "atp" | "wta" | "itf";
|
|
1507
|
+
/** The match's draw. qualification when the provider competition label carries Polymarket's qualifying mark (", Qualification", which 0xinsider also applies when Polymarket flags an ATP Challenger qualifying fixture); main for an unmarked ATP or WTA label. Omitted for an unmarked ITF label: Polymarket gives an ITF qualifying match the main draw's label. */
|
|
1508
|
+
draw?: "main" | "qualification";
|
|
1509
|
+
/** The edition's verified category, for example "ATP Masters 1000", "ATP Challenger 50", "WTA 1000" or "ITF M25". Omitted when no official page states it. */
|
|
1510
|
+
tier?: string;
|
|
1511
|
+
/** The verified venue city and country. Omitted when no official page states it. */
|
|
1512
|
+
location?: GameTournamentLocation;
|
|
1513
|
+
/** The venue's IANA time zone, for example "Europe/Rome". Format the venue's local time with it; it carries the daylight-saving rules. Omitted when the venue is unverified. */
|
|
1514
|
+
timezone?: string;
|
|
1515
|
+
/** The year of the edition. */
|
|
1516
|
+
edition_year: number;
|
|
1517
|
+
/** The edition's first official day, inclusive (YYYY-MM-DD). A qualifying match can be played up to two days before it. */
|
|
1518
|
+
starts_on: string;
|
|
1519
|
+
/** The edition's last official day, inclusive (YYYY-MM-DD). */
|
|
1520
|
+
ends_on: string;
|
|
1521
|
+
/** The official tournament, tour, federation or time-zone pages the facts were taken from. */
|
|
1522
|
+
source_urls: string[];
|
|
1523
|
+
/** When those pages were checked: a catalogue verification date, not a score or price clock. */
|
|
1524
|
+
checked_on: string;
|
|
1525
|
+
};
|
|
1526
|
+
/** A verified tournament venue. */
|
|
1527
|
+
export type GameTournamentLocation = {
|
|
1528
|
+
city: string;
|
|
1529
|
+
country: string;
|
|
1530
|
+
/** ISO 3166-1 alpha-2, for example "IT". */
|
|
1531
|
+
country_code: string;
|
|
1532
|
+
};
|
|
1493
1533
|
/** One fill in a game, as the game page's activity list shows it. */
|
|
1494
1534
|
export type GameTrade = {
|
|
1495
1535
|
/** Stable fill identity: {transaction_hash}:{token_id}:{wallet}:{shares}. Deduplicate on it across polls. */
|
|
@@ -2013,8 +2053,8 @@ export type MarketHolder = {
|
|
|
2013
2053
|
category_avg_price?: number;
|
|
2014
2054
|
/** Where `category_win_rate` and `category_win_record` were measured: for an esports market the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a market in a registered league that league, by the name Pick of the Day uses for it (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other market, and beside every non-measured status. Label the rate with this when present and with the market's `category` otherwise. */
|
|
2015
2055
|
category_win_rate_game?: string;
|
|
2016
|
-
/** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (under the floor of 5 decided markets in the category), or `unavailable` (the market has no canonical category, or the read failed; retry later). Always present on this route. */
|
|
2017
|
-
category_win_rate_status: "measured" | "not_enough_data" | "unavailable";
|
|
2056
|
+
/** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (under the floor of 5 decided markets in the category), or `unavailable` (the market has no canonical category, or the read failed; retry later). Never `untracked`: this route lists S, A and B wallets only, all on file. Always present on this route. */
|
|
2057
|
+
category_win_rate_status: "measured" | "not_enough_data" | "unavailable" | "untracked";
|
|
2018
2058
|
category_evidence?: HolderCategoryEvidence;
|
|
2019
2059
|
/** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request. The five badge fields are present together, only for a wallet that draws at least one badge. */
|
|
2020
2060
|
wallet_age_days?: number | null;
|
|
@@ -2238,8 +2278,8 @@ export type MarketTopHolder = {
|
|
|
2238
2278
|
category_avg_price?: number;
|
|
2239
2279
|
/** Where `category_win_rate` and `category_win_record` were measured: for an esports market the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a market in a registered league that league, by the name Pick of the Day uses for it (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other market, and beside every non-measured status. Label the rate with this when present and with the market's `category` otherwise. */
|
|
2240
2280
|
category_win_rate_game?: string;
|
|
2241
|
-
/** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (under the floor of 5 decided markets in the category), or `unavailable` (
|
|
2242
|
-
category_win_rate_status?: "measured" | "not_enough_data" | "unavailable";
|
|
2281
|
+
/** Why `category_win_rate` is present or absent: `measured` (rate present), `not_enough_data` (the wallet is on file and under the floor of 5 decided markets in the category), `untracked` (0xinsider has no record of the wallet, so nothing was measured; `grade`, `in_scope_realized_pnl` and `in_scope_volume` are null too), or `unavailable` (a read failed; retry later). Absent when the market has no canonical category. */
|
|
2282
|
+
category_win_rate_status?: "measured" | "not_enough_data" | "unavailable" | "untracked";
|
|
2243
2283
|
/** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request. The five badge fields are present together, only for a wallet that draws at least one badge. */
|
|
2244
2284
|
wallet_age_days?: number | null;
|
|
2245
2285
|
/** True when the wallet's first trade was under 30 days ago. */
|
|
@@ -2266,6 +2306,8 @@ export type MarketTopHolders = {
|
|
|
2266
2306
|
computed_at?: string;
|
|
2267
2307
|
/** When Polymarket's holder board behind this sample was fetched: up to 120 s before `computed_at` on an open market. Absent on a resolved market, whose sample reads no live board, and when the fetch stamp could not be read. */
|
|
2268
2308
|
positions_as_of?: string;
|
|
2309
|
+
/** `true` when this is the market's last sample, served after its 30 s window while a refresh runs; `positions_as_of` is then at most 300 s old. Read again in a few seconds for the refreshed sample. Always `false` on a resolved market. */
|
|
2310
|
+
source_stale: boolean;
|
|
2269
2311
|
};
|
|
2270
2312
|
export type MarketTopHoldersTotals = {
|
|
2271
2313
|
/** Holders in the YES sample, before `limit`. Equal to `sample_cap` means that many or more. */
|
|
@@ -2374,8 +2416,8 @@ export type PickHolder = {
|
|
|
2374
2416
|
category_avg_price?: number;
|
|
2375
2417
|
/** Where `category_win_rate` and `category_win_record` were measured, by the same name the pick's `display_category` uses for it: for an esports pick the game (`LoL`, `CS2`, `Dota 2`, `Valorant`, `Call of Duty`, `Honor of Kings`, `Mobile Legends: Bang Bang`, `Overwatch`, `Rainbow Six Siege`, `Rocket League` or `StarCraft II`), and for a pick in a registered league that league (`NBA`, `NFL`, `NHL`, `MLB`, `UFC`, `ATP`, `WTA`, `LaLiga`, `Premier League`, `Serie A`, `UEFA Champions League`, `MLS` and the other registered leagues). Present only when the wallet's record there clears the 5-settled-market floor, in which case the rate and record are the game's or league's rather than the whole `category` bucket's. Absent when the rate is the bucket's (the wallet's history there is under the floor, or the competition is not a registered league), on every other pick, beside every non-measured status, and on payloads predating the field. Label the rate with this when present and with `category` otherwise. */
|
|
2376
2418
|
category_win_rate_game?: string;
|
|
2377
|
-
/** Why `category_win_rate` is present or absent on a `display_holders` entry: `measured` (rate present), `not_enough_data` (the wallet is below the settled-market floor of 5 in the category), or `unavailable` (the annotation read failed; retry later). Absent entirely on `holders` entries, legacy rows, and payloads predating the field -- absence means the roster was never annotated, not a small sample. */
|
|
2378
|
-
category_win_rate_status?: "measured" | "not_enough_data" | "unavailable";
|
|
2419
|
+
/** Why `category_win_rate` is present or absent on a `display_holders` entry: `measured` (rate present), `not_enough_data` (the wallet is below the settled-market floor of 5 in the category), or `unavailable` (the annotation read failed; retry later). Never `untracked`: every recorded holder is a graded wallet 0xinsider has on file. Absent entirely on `holders` entries, legacy rows, and payloads predating the field -- absence means the roster was never annotated, not a small sample. */
|
|
2420
|
+
category_win_rate_status?: "measured" | "not_enough_data" | "unavailable" | "untracked";
|
|
2379
2421
|
/** Whole days since this wallet's first trade, rounded down (3.6 days reads 3), so it changes once a day, not on every request, and the pick's ETag holds between requests. Stamped at serve time from the wallet's current trader record, never frozen with the pick. The five badge fields are present together, and only for a wallet that carries at least one badge; all absent means no badge, or a body cached before the fields shipped. */
|
|
2380
2422
|
wallet_age_days?: number | null;
|
|
2381
2423
|
/** True when the wallet's first trade was under 30 days ago. Stamped at serve time from the wallet's current trader record, never frozen with the pick. The five badge fields are present together, and only for a wallet that carries at least one badge; all absent means no badge, or a body cached before the fields shipped. */
|
|
@@ -4113,7 +4155,7 @@ export type Trader = {
|
|
|
4113
4155
|
* @deprecated
|
|
4114
4156
|
*/
|
|
4115
4157
|
realized?: number;
|
|
4116
|
-
/** Unrealized P&L in USD of the wallet's open positions on its synced sports and esports markets, from the open-position aggregate (dated by the positions data_quality group). Each open position's market is judged when the aggregate is read (#32119), so a stored position on a market of another category (one that moved out of sports and esports, or one stored before its category was known) is left out. Before 2026-10-27 (#29366) it covered every Polymarket market. */
|
|
4158
|
+
/** Unrealized (mark-to-market) P&L in USD of the wallet's open positions on its synced sports and esports markets: Polymarket's cashPnl, current value minus cost, summed over the positions still held, from the open-position aggregate (dated by the positions data_quality group). It is the same figure as position_summary.unrealized_mtm on GET /api/v1/trader/{address}/context. It leaves out the realized P&L of partial sells on those markets, which pnl.in_scope.realized_pnl already counts; until 2026-11-02 (#32459) it added it, so pnl.in_scope.realized_pnl plus pnl.unrealized counted those sells twice. Each open position's market is judged when the aggregate is read (#32119), so a stored position on a market of another category (one that moved out of sports and esports, or one stored before its category was known) is left out. Before 2026-10-27 (#29366) it covered every Polymarket market. */
|
|
4117
4159
|
unrealized?: number;
|
|
4118
4160
|
/**
|
|
4119
4161
|
* Deprecated since 2026-10-27 and never sent: its one member was the lossless counterpart of the retired pnl.realized (#29830).
|
|
@@ -4237,7 +4279,7 @@ export type TraderContext = {
|
|
|
4237
4279
|
synced_realized_pnl: number;
|
|
4238
4280
|
/** Native net realized P&L (USD) over every Polymarket market of the wallet, including credited rebates, read directly from the accounting snapshot. For the sports and esports figure read trader.pnl.in_scope.realized_pnl. Position sync_coverage is separate from this accounting basis. */
|
|
4239
4281
|
total_realized_pnl: number;
|
|
4240
|
-
/** Mark-to-market unrealized P&L (USD) on open positions in synced sports and esports markets (#32119). */
|
|
4282
|
+
/** Mark-to-market unrealized P&L (USD) on open positions in synced sports and esports markets (#32119): Polymarket's cashPnl summed over the positions still held, without the realized P&L of partial sells. The same figure as trader.pnl.unrealized, in this body and on GET /api/v1/trader/{address}, since 2026-11-02 (#32459). */
|
|
4241
4283
|
unrealized_mtm: number;
|
|
4242
4284
|
/** Cost basis (USD) currently tied up in open positions in synced sports and esports markets (#32119). */
|
|
4243
4285
|
cost_basis_locked: number;
|
|
@@ -5600,8 +5642,8 @@ export interface OperationQuery {
|
|
|
5600
5642
|
category?: string;
|
|
5601
5643
|
/** Required for view=observations; wider_holder, in_play or emerging_pile. Rejected for board and signals. wider_holder covers pregame markets that view=signals does not list at its widest selection (horizon_hours=48, min_grade=B, no selector), so until kickoff a market is read in one view or the other. A market view=signals lists leaves wider_holder as primary_slate_candidate, and is a wider_holder candidate again in the first refresh after view=signals stops listing it; signals_as_of names the view=signals snapshot each refresh read. Each refresh evaluates at most 8 markets per sport and cohort, wider_holder by soonest kickoff (most graded holders first among equal kickoffs) and in_play by most graded holders, so a market among a sport's 8 soonest stays evaluated until its game starts. wider_holder also evaluates up to 8 more markets per sport that kick off within 24 hours, most graded holders first, so the most-held markets appear up to a day before kickoff. Each of these keeps its place in later refreshes until its game starts while its holder page still shows a card or could not be read, so a more-held market waits for a free place instead of displacing it. Each row's admitted_by names its place, most_held or soonest_kickoff. The rest count in coverage.capacity_limited_markets. Emerging pile is a wider-holder projection with sharp_pct in [0.75,0.85), complete holder scans and future kickoff, not an independent population or arrival history. */
|
|
5602
5644
|
cohort?: "wider_holder" | "in_play" | "emerging_pile";
|
|
5603
|
-
/** Opt-in admission rule for view=observations with cohort=wider_holder; rejected for every other view and cohort. most_held_48h returns the most-held selection instead of the default one: per sport, up to 8 wider_holder markets kicking off within 48 hours, most graded holders first, then most volume, then soonest kickoff, at most 4 per event. It is recomputed every refresh and keeps no place, so a more-held market displaces a less-held one; markets view=signals lists stay excluded. Every row carries admitted_by most_held_48h, including a market the default selection also evaluates, and the response echoes admission. funnel, coverage, degraded and degradation_reasons describe this selection: a wider_holder candidate it did not take counts as capacity_limited. Its markets that no default place covers are read after every default market, at most once per 10 minutes, so a row can rest on a holder page up to 15 minutes old (holder_snapshot_at). Omit for the default selection. Cursors and ETags bind it. */
|
|
5604
|
-
admission?: "most_held_48h";
|
|
5645
|
+
/** Opt-in admission rule for view=observations with cohort=wider_holder; rejected for every other view and cohort. most_held_48h returns the most-held selection instead of the default one: per sport, up to 8 wider_holder markets kicking off within 48 hours, most graded holders first, then most volume, then soonest kickoff, at most 4 per event. It is recomputed every refresh and keeps no place, so a more-held market displaces a less-held one; markets view=signals lists stay excluded. Every row carries admitted_by most_held_48h, including a market the default selection also evaluates, and the response echoes admission. funnel, coverage, degraded and degradation_reasons describe this selection: a wider_holder candidate it did not take counts as capacity_limited. Its markets that no default place covers are read after every default market, at most once per 10 minutes, so a row can rest on a holder page up to 15 minutes old (holder_snapshot_at). most_held_48h_by_type requires market_types and runs the same rule within each named type: per sport and market_context.market_type, up to 8 markets (4 per event), most graded holders first, then volume, then soonest kickoff, so a type whose markets hold fewer wallets than team-win markets still gets its own places. Its rows carry admitted_by most_held_48h_by_type and it has no departures. Its markets no other selection read are read after every default and most_held_48h market, at most once per 10 minutes. A market type not asked for in the last 30 minutes answers 503 read_model_warming with Retry-After 45 s while the next refresh computes it. Omit for the default selection. Cursors and ETags bind it. */
|
|
5646
|
+
admission?: "most_held_48h" | "most_held_48h_by_type";
|
|
5605
5647
|
/** Board and signals: S, A or B, default B. Requires a piled-side holder at the selected grade floor or better, without removing other holders. Rejected for observations. */
|
|
5606
5648
|
min_grade?: "S" | "A" | "B";
|
|
5607
5649
|
/** Board row cap defaults to 30 and clamps integer values to 1..30; total counts selected admitted rows before the cap. Signals and observations page size defaults to 20 and clamps to 1..100. */
|
|
@@ -5766,7 +5808,7 @@ export interface OperationQuery {
|
|
|
5766
5808
|
"expand[]"?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
|
|
5767
5809
|
/** Include heavy fields and trust metadata. Repeatable: strategy, categories, trust. quant_metrics is accepted and returns nothing since 2026-10-27. */
|
|
5768
5810
|
expand?: ("strategy" | "categories" | "quant_metrics" | "trust")[];
|
|
5769
|
-
/** Opt into a whole-response freshness ceiling in seconds. The server returns 200 only when data_quality.status is fresh and data_quality.as_of is no older than this value; otherwise it returns 409 with error.reason=freshness_ceiling_unsatisfied. No refresh or alternate read is attempted. */
|
|
5811
|
+
/** Opt into a whole-response freshness ceiling in seconds. The server returns 200 only when data_quality.status is fresh or stale and data_quality.as_of is no older than this value; otherwise it returns 409 with error.reason=freshness_ceiling_unsatisfied. No refresh or alternate read is attempted. */
|
|
5770
5812
|
max_age_s?: number;
|
|
5771
5813
|
};
|
|
5772
5814
|
getTraderCategoryRecords: {
|