Skip to main content

Audience

This surface is for partners running off-platform copies of the trade log — typically auditors and regulator-tech integrations. It is not for retail wallet flows; for a single user’s own trades use GET /api/me/trades. Two endpoints:
  1. GET /api/v1/partner/trades — incremental, cross-wallet trade feed.
  2. GET /api/v1/partner/reconciliation/snapshot — window-aggregate cross-check.

Authentication

Both endpoints use API-key auth.
  • Header: X-Api-Key: ps_live_<keyId>_<secret>
  • Required scope: partner:trades:read
  • The scope is read-only by design — admin refuses to issue a key that mixes partner:trades:read with any write scope (orders:write, vault:write). A partner using this surface cannot place orders or move funds with the same key.
  • Privy JWT sessions are explicitly rejected on these endpoints — they are partner-only.
The scope is selectable in the admin-panel API-key issuance form (checkbox alongside markets:read, events:read, etc.).

Trades feed

Cross-wallet executed-trade feed. Cursor-paginated and incremental by modification time.

Query parameters

Response — 200 OK

PartnerTrade:
PartnerTradeFee:
PartnerTradeSide (identical shape on taker and maker):

Example

Behaviour notes

  • Idempotency. A single trade may surface twice — once when matched (status='matched', settledAt: null), again when settlement lands (status='settled', settledAt: <iso>). Partners are expected to upsert by tradeId.
  • In-walk re-emit. The same trade can re-emit within a single cursor walk if its settlement lands between page N and N+1. Same upsert rule applies.
  • modifiedSince must stay constant across all cursor pages of a single drain.
  • Settlement failures are emitted with status='settlement_failed' — partners must NOT filter these out client-side.

Status codes

Rate limit

  • Per API-key: 600 requests / minute (default; can be raised per partner via partner.rate_limit_per_min).
  • Per IP: 1000 requests / minute (defence-in-depth on egress IP).

Reconciliation snapshot

Window-aggregate cross-check for a partner’s local copy of trades. Returns counts, sums, and a deterministic content hash over the trade ids in the window.

Query parameters

The from / to bounds use the same max(createdAt, settledAt) expression as the trade feed’s modifiedSince. The window aligns 1:1 with trades the partner pulled via ?modifiedSince=.

Response — 200 OK

Fingerprint algorithm

sha256 of the trade ids in the window, sorted lexicographically as decimal strings and joined by commas:
Sort as strings, not as integers. ["1", "10", "2"], not ["1", "2", "10"]. The server matches the default sort order in Python / JavaScript / Go.
Empty-window canonical (no trades in [from, to)): e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 (SHA-256 of the empty string).

Stability

Status codes

Rate limit

  • Per API-key: 60 requests / minute (recon is meant for periodic polling, not high-frequency).
  • Per IP: 200 requests / minute.

Error envelope

All errors follow the project-standard JSON shape:

Codes used by these endpoints