Skip to content

feat!: migrate data reads to the Data API v2 contract - #297

Merged
kartojal merged 8 commits into
mainfrom
integration/data-api-v2
Sep 10, 2026
Merged

feat!: migrate data reads to the Data API v2 contract#297
kartojal merged 8 commits into
mainfrom
integration/data-api-v2

Conversation

@kartojal

@kartojal kartojal commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Migrates portfolio, activity, analytics, price history, and leaderboards to cursor-paginated Data API v2 across all four clients. Adds bounded 429 retries and typed metrics/resolutions. Port pinned to ts-sdk 6e5c293 (upstream rechecked).

BREAKING CHANGE: removes list_closed_positions, list_market_positions, get_traded_market_count, and get_price_history; use list_positions, get_user_stats, and list_price_history. Renames get_portfolio_valuesget_portfolio_value, get_market_holderslist_market_holders, and get_event_live_volumesget_event_live_volume. Fields/frame columns use current_size, current_price, explicit cost/PnL fields, wallet, taker_volume_total, volume, and builder names/calendar dates; legacy token aliases remain. Default page size is 100 (history: 10000). Leaderboard windows are lowercase; ranks are integers.

Validation: 2,331 unit tests; 15 live data workflows (production data, staging auth); Ruff, Pyright, Sphinx, pandas/Polars. Full integration suite has 24 failures and four non-data setup errors reproduced on untouched main with the supplied credentials.

Before merge: confirm the intended release version (bump-minor-pre-major is unset). Supersedes #270 and #272. Follow-ups: #298 and #299.


Note

High Risk
Large breaking change across all four clients—pagination, method names, and position field names will break existing integrations; core portfolio and history reads now depend on new v2 semantics and validation rules.

Overview
BREAKING: Portfolio, activity, analytics, leaderboards, and price history now go through Data API v2 (/v2/*) with cursor keyset pagination (default page size 100; price history default 10000). Offset-paginated v1 data paths and several standalone endpoints are removed or folded into unified methods.

Public API reshaping: list_closed_positions and list_market_positions are gone—use list_positions with status="CLOSED" or a single condition_id. get_traded_market_count is replaced by get_user_stats. CLOB get_price_history is removed in favor of list_price_history on the data service (interval, bounded window, or as_of). Renames include get_portfolio_valuesget_portfolio_value, holders as list_market_holders, and get_event_live_volume (plural volumes removed). Filters shift from market to condition_id, with shared param builders for condition IDs, event IDs, and timezone-aware start/end. full_history remains on trades, activity, positions, and user volume (documented as a narrow exception).

New capabilities: user PnL/volume series, resolutions lookup, biggest winners, trader leaderboard standing, expanded builder volume buckets, and typed filter/sort aliases (LeaderboardWindow, PositionStatusFilter, etc.). Data models and analytics types are re-exported from polymarket.models.data.

Models & internals: Position uses current_size / current_price (relayer merge logic updated). v2 responses parse through data + pagination envelopes; data reads get bounded 429 retries. Examples and SDK direction docs reflect the new field names and enum input/output patterns.

Reviewed by Cursor Bugbot for commit d8aaa92. Bugbot is set up for automated code reviews on this repo. Configure here.

@kartojal
kartojal marked this pull request as ready for review September 9, 2026 08:53
kartojal and others added 4 commits September 9, 2026 11:17
… enums

Reject an explicit empty user on list_trades, a bare string for
activity_types, and an empty leaderboard category, which is now sent
as given instead of lowercased. Allow include_archived=False with
CLOSED positions and zero-length price history windows, matching the
service. Send condition_id on every route. Reject a missing event id
on market biggest winners and accept epoch zero on activity rows.

Output vocabularies such as PositionStatus, ActivityType, and
ResolutionStatus are StrEnum types, with *Filter and *Input aliases
that keep plain-string inputs working. Live volume is documented in
shares.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Date-only ISO strings on combo leg markets and resolutions parse as
midnight UTC instead of naive datetimes, which also removes the frames
warning. Market biggest winners require a positive decimal event id.
Covers the end-before-start price window and enum-member inputs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@naruto11eth

Copy link
Copy Markdown
Contributor

Reviewed the Data API v2 migration across all four clients, including pagination, response models, retries, and the backend contract. The overall structure looks good, and the unit suite, lint, and type checks passed during review.

There are two request-contract edge cases I’d like addressed before merging:

1. full_history=True can exclude legitimate positions.

list_positions_spec uses the shared time-window helper, which translates full history into start=1. However, positions are already unbounded when no time parameters are supplied. The backend excludes positions with a missing last_event_at whenever a time bound is present.

Consequently, requesting full history can return fewer holdings than the default request, without any error. Please handle the positions case separately by omitting both bounds for full history, while retaining validation against combining it with explicit bounds. The other feeds have different default-window semantics, so I wouldn’t change the shared helper globally. A regression covering a holding without an activity timestamp would pin this.

2. Combo synchronization no longer accepts zero watermarks.

updated_after and updated_before now use _check_timestamp, which requires a strictly positive value. The previous SDK accepted zero, and the backend explicitly tests zero as valid.

This breaks callers initializing synchronization with updated_after=0. Omitting the parameter is not equivalent: without a status filter, supplying a watermark selects the mirror-complete synchronization view rather than the default held-position listing. Please allow nonnegative values for these watermarks and retain the existing ordering validation.

One documentation correction: BuilderStanding, BuilderVolumePoint, and the corresponding client methods describe builder volume as USDC. The backend returns share counts; its legacy volume_usdc column name is misleading. Please change the descriptions to shares, leaving the values and field names unchanged.

One non-blocking convention question: the new full_history boolean appears to conflict with the SDK guidance against boolean mode flags. Please confirm this is an intentional exception or whether an explicit time-window shape is preferred. I’m not suggesting a broad redesign as part of these fixes.

@kartojal
kartojal merged commit 599afce into main Sep 10, 2026
7 checks passed
@kartojal
kartojal deleted the integration/data-api-v2 branch September 10, 2026 16:16
@kartojal

kartojal commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Reviewed the Data API v2 migration across all four clients, including pagination, response models, retries, and the backend contract. The overall structure looks good, and the unit suite, lint, and type checks passed during review.

There are two request-contract edge cases I’d like addressed before merging:

1. full_history=True can exclude legitimate positions.

list_positions_spec uses the shared time-window helper, which translates full history into start=1. However, positions are already unbounded when no time parameters are supplied. The backend excludes positions with a missing last_event_at whenever a time bound is present.

Consequently, requesting full history can return fewer holdings than the default request, without any error. Please handle the positions case separately by omitting both bounds for full history, while retaining validation against combining it with explicit bounds. The other feeds have different default-window semantics, so I wouldn’t change the shared helper globally. A regression covering a holding without an activity timestamp would pin this.

2. Combo synchronization no longer accepts zero watermarks.

updated_after and updated_before now use _check_timestamp, which requires a strictly positive value. The previous SDK accepted zero, and the backend explicitly tests zero as valid.

This breaks callers initializing synchronization with updated_after=0. Omitting the parameter is not equivalent: without a status filter, supplying a watermark selects the mirror-complete synchronization view rather than the default held-position listing. Please allow nonnegative values for these watermarks and retain the existing ordering validation.

One documentation correction: BuilderStanding, BuilderVolumePoint, and the corresponding client methods describe builder volume as USDC. The backend returns share counts; its legacy volume_usdc column name is misleading. Please change the descriptions to shares, leaving the values and field names unchanged.

One non-blocking convention question: the new full_history boolean appears to conflict with the SDK guidance against boolean mode flags. Please confirm this is an intentional exception or whether an explicit time-window shape is preferred. I’m not suggesting a broad redesign as part of these fixes.

Decided to add a rule to keep full_history boolean at AGENTS.md to be on par with ts-sdk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants