Skip to main content

Trade History

GET /v1/account/history
Returns your filled orders (trade history) with filtering and pagination.

Authentication

API key only — X-API-Key: <key> (or the PM-compat POLY_API_KEY / Authorization: Bearer ps_live_... aliases). A Supabase Bearer JWT is not accepted here.

Query Parameters

ParameterTypeDefaultDescription
market_idstringFilter by condition_id
sidestringFilter: BUY or SELL
limitint50Max results (1–200)
offsetint0Pagination offset
wallet_idint | "all" | "api"apiWallet scope. An integer scopes to a single wallet you own (404 WALLET_NOT_FOUND otherwise). api scopes to your API wallet (including legacy rows recorded before per-wallet attribution). all returns filled orders across all your wallets, UI MAIN/SANDBOX included. Keywords are case-insensitive; any other value returns 422 VALIDATION_FAILED. Omitted = api.
envelopeboolfalseWhen true, wrap the response in the Polymarket-shape { "data": [...], "next_cursor": "<offset>" } envelope. next_cursor carries the next offset value as a string when a full page was returned (more rows likely exist), else "". Default false returns the bare array.
Default changed on 2026-06-10. Before 2026-06-10 the default (param omitted) returned filled orders across all wallets — UI MAIN/SANDBOX included. The default is now the API wallet, consistent with Balance / Portfolio / Equity Curve. Pass wallet_id=all if you depended on the old cross-wallet behaviour.

Request

# All recent trades
curl -H "X-API-Key: $API_KEY" \
  "https://api.polysimulator.com/v1/account/history?limit=20"

# Only sells for a specific market
curl -H "X-API-Key: $API_KEY" \
  "https://api.polysimulator.com/v1/account/history?market_id=0x1a2b3c&side=SELL"

Response

Orders are returned most-recent first (descending filled_at).
[
  {
    "order_id": 42,
    "market_id": "0x1a2b3c...",
    "side": "BUY",
    "outcome": "Yes",
    "price": "0.65",
    "quantity": "10.0",
    "notional": "6.50",
    "fee": "0.09",
    "status": "FILLED",
    "price_source": "clob_midpoint_live",
    "price_age_ms": 12,
    "filled_at": "2026-02-06T12:00:45Z",
    "created_at": "2026-02-06T12:00:45Z"
  }
]
FieldTypeDescription
order_idintOrder ID
market_idstringMarket condition_id
sidestringBUY or SELL
outcomestringOutcome name (e.g. Yes / No)
pricestringFill price per share (string-encoded decimal)
quantitystringNumber of shares filled (string-encoded decimal)
notionalstringTotal cash value of the fill (price × quantity), string-encoded decimal
feestringTaker fee charged on the fill, string-encoded decimal (USD) — the real PM-V2 per-category fee C × feeRate × p × (1 − p) (example: 10-share BUY at 0.65ona40.65 on a 4% politics market → `10 × 0.04 × 0.65 × 0.35 = 0.09). 0.00for fee-free fills (maker fills, geopolitics markets, emergency exits). Note: crypto rows filled before 2026-06-10 may have been charged the prior 7.2% rate, while rate-reporting fields (e.g.fee_rate_bpsonGET /v1/data/trades) report the current 700 bps — the stored fee` is always the authoritative debited amount. See Trading Fees.
statusstringSimulator order status. For trade history this is always FILLED (the endpoint returns filled orders only). See the note below on Polymarket parity.
price_sourcestring | nullFree-form label for how the fill price was sourced (e.g. clob_midpoint_live, clob_midpoint_cached_hft, matching_engine, ws:<source>, emergency_exit_entry_price). null on legacy rows.
price_age_msint | nullAge of the price data at execution time, in milliseconds; null when not recorded
filled_atstring | nullISO-8601 UTC fill timestamp
created_atstring | nullISO-8601 UTC order-creation timestamp
Polymarket parity: PolySimulator fills paper orders instantly, so the status here is the simulator’s order status (FILLED), not Polymarket’s on-chain trade lifecycle (MATCHED → MINED → CONFIRMED, with RETRYING / FAILED). There is no settlement-finality state to track for simulated trades. If you are porting a Polymarket SDK, treat FILLED as equivalent to a terminal CONFIRMED trade.
With envelope=true the rows are wrapped Polymarket-style, with a real cursor:
{
  "data": [ /* … same row objects … */ ],
  "next_cursor": "50"
}
next_cursor is the next offset value (as a string) when a full page was returned; it is "" when the page was short (no more rows).

Errors

All errors return {"error": "<CODE>", "message": "<human-readable>"}.
Statuserror codeWhen
401MISSING_API_KEYNo API key header supplied
401INVALID_KEYAPI key is unknown, deactivated, or expired
404WALLET_NOT_FOUNDInteger wallet_id does not exist or is not owned by the caller
422VALIDATION_FAILEDwallet_id is neither an integer, all, nor api

Next Steps