Account data
Account data
All account-data query types accept a public wallet address and do not require authentication. Where supported, broker_id and account_id narrow the lookup; use pangoperps for PangoPerps account scope. Account values and monetary amounts are decimal strings.
Account state
Returns account collateral, margin, PnL, and currently open positions. Weight: 5. Supplying account_id returns one account as a flat object; omitting it returns an accounts[] list.
{
"type": "accountState",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"broker_id": "pangoperps",
"account_id": "0xabc..."
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address. |
| broker_id | string | No | Optional broker filter. |
| account_id | string | No | Optional account filter; when supplied, data is the flat account object. |
Account fields include address, broker_id, account_id, account_type, account_value, total_collateral_value, free_collateral, margin_ratio, initial_margin_ratio, maintenance_margin_ratio, total_unrealized_pnl, total_unsettled_pnl, total_pnl_24_h, and positions[]. account_type is main, sub, or sp (vault strategy provider). account_value is collateral plus unrealized PnL; total_collateral_value includes token holdings, isolated margin, and frozen collateral, with non-USDC balances valued using the spot index price. free_collateral is approximately collateral multiplied by (1 - margin_ratio). initial_margin_ratio is calculated over cross-margin positions; maintenance margin is the minimum ratio needed to avoid liquidation.
Each open-position row contains symbol, side, position_qty, notional, average_open_price, mark_price, unrealized_pnl, unsettled_pnl, pnl_24_h, imr, mmr, est_liq_price, leverage, margin_mode, opened_at, and updated_at. Quantity is signed; side is LONG for a positive quantity and SHORT for a negative quantity. notional is absolute quantity times mark price. margin_mode is CROSS or ISOLATED. PnL, margin, and price-derived fields can be null if position calculation is unavailable. Only open positions (nonzero holdings) are returned. A missing account returns ADDRESS_NOT_FOUND (404); position-calculation failure does not suppress other account data.
Accounts
Lists the main and sub-accounts controlled by a wallet. Use this as the discovery query before requesting a particular account's state. Weight: 5; no pagination.
{
"type": "accounts",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"broker_id": "pangoperps"
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address; it must resolve to at least one account. |
| broker_id | string | No | Optional broker filter. |
data contains the input address and accounts[]. Each entry includes broker_id, account_id, account_type (main, sub, or sp), and account_value. Account value is calculated as (holding + iso_margin_total + frozen) + Σ unrealized_pnl across positions. It can be null if position calculation is unavailable for that account. If no accounts resolve, the API returns ADDRESS_NOT_FOUND (404). Per-account calculation failures set only that account's value to null.
Agent context
Returns a startup bundle containing an account snapshot, open positions, summaries for markets held by that account, and the open-order count. The constituent lookups run in parallel. Weight: 2.
{
"type": "agentContext",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"broker_id": "pangoperps",
"account_id": "0xabc..."
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address. |
| broker_id | string | No | Optional broker filter. |
| account_id | string | No | Optional account filter. If omitted, the primary account is selected by highest account value, with a main account used to break ties. |
data includes account, positions[], and markets[]. The account object is a subset of accountState and adds open_order_count; if that subquery fails, the count defaults to 0. Positions follow accountState.positions[]. Each market row corresponds to a held symbol and follows the marketSummary row format with an added 24h_change_pct, calculated as (close - open) / open × 100. Markets not held by the selected account are not included. For the complete open-order list, use openOrders. This bundle uses weight 2, compared with the separate-call total of 11 for accountState, openOrders, and marketSummary.
Fee rate
Returns a user's fee tier, maker/taker rates, and executed notional over the last 30 days. Weight: 1. The response format depends on the supplied filters.
{
"type": "feeRate",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"broker_id": "pangoperps",
"account_id": "0xabc..."
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address. |
| broker_id | string | No | With no account_id, returns a sub_accounts[] result for the broker. |
| account_id | string | No | Returns one account as a flat object. |
Provide both address and account_id for a flat account object; provide address and broker_id without account_id for sub_accounts[]; provide only address for accounts[]. Each account entry contains broker_id, account_id, account_type, tier, futures_tier, maker_fee_rate, taker_fee_rate, and 30d_volume.
tier and futures_tier can be PUBLIC, SILVER, GOLD, PLATINUM, or DIAMOND; they may be null. Maker and taker rates are decimal strings (bps / 10000) and may be null. 30d_volume is executed perpetual notional over the past 30 days, returned as a decimal string ("0" when there is no volume). Results are cached for 60 seconds by address and filters. No matching account returns ADDRESS_NOT_FOUND (404).
Funding payments
Returns funding-fee history for a wallet, including payment direction and settlement state. Weight: 5.
{
"type": "fundingPayments",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"symbol": "PERP_BTC_USDC",
"start_time": 1715000000000,
"limit": 100
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id | string | No | — | Optional broker filter. |
| account_id | string | No | — | Optional account filter. |
| symbol | string | No | — | Market filter. |
| start_time, end_time | int64 | No | — | Time-window bounds in milliseconds. |
| limit | int | No | 100; 1–500 | Maximum rows. |
| cursor | string | No | — | Opaque pagination cursor. |
With no time filters, the query returns the full available history. Each row includes symbol, funding_rate, funding_fee, position_qty, mark_price, funding_rate_timestamp, payment_type, funding_status, and margin_mode. The fee is signed: positive means the user paid, negative means the user received. payment_type is Pay, Receive, or null when the fee is zero. funding_status is Settled or Accrued; it defaults to Settled if the settlement table cannot be read. margin_mode is CROSS or ISOLATED. The position and mark price are snapshots from the funding interval. Results use data.next_cursor for pagination.
Historical orders
Returns closed orders with status FILLED, CANCELLED, or REJECTED. It queries live and archived data, including windows that cross the 92-day archive boundary. Both standard and algorithmic orders are included. Weight: 5.
{
"type": "historicalOrders",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"symbol": "PERP_ETH_USDC",
"status": "FILLED",
"start_time": 1715000000000,
"end_time": 1715600000000,
"limit": 100
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| symbol | string | No | — | Market filter. |
| status | string | No | All three statuses | FILLED, CANCELLED (also accepts CANCELED), or REJECTED; case-insensitive. |
| start_time | int64 | No | UTC-day-aligned now - 24h | Start time in milliseconds. |
| end_time | int64 | No | now | End time in milliseconds. |
| limit | int | No | 100; 1–500 | Maximum rows. |
| cursor | string | No | — | Opaque pagination cursor. |
Order rows include order_id, symbol, side, type, price, quantity, total_executed_quantity, average_executed_price, trigger_price, trigger_status, status, total_fee, fee_asset, realized_pnl, reduce_only, created_time, and updated_time. order_id is a string-encoded 64-bit value. type may be a standard type (LIMIT, MARKET, IOC, POST_ONLY, FOK, LIQUIDATE, BID, ASK, SETTLEMENT) or an algorithmic type (STOP_MARKET, STOP_LIMIT, TAKE_PROFIT_MARKET, TAKE_PROFIT_LIMIT, OCO, TRAILING_STOP, BRACKET, POSITIONAL_TP_SL, TP_SL, STOP_TRIGGER, STOP_BRACKET). average_executed_price is calculated from executed amount divided by executed quantity, and is null when there are no fills. Algorithmic rows can include trigger fields; realized_pnl can be null for algorithmic rows.
If status is omitted, all three closed statuses are queried (FILLED → [3], CANCELLED → [5], REJECTED → [6]). The default start time is aligned to a UTC day; specify start_time for a longer lookback. Live and archived records are combined automatically. Rows are sorted by created_time descending, then order_id descending. Use data.next_cursor to continue.
Open orders
Returns open and partially filled standard and algorithmic orders for a wallet, sorted newest first. Weight: 5.
{
"type": "openOrders",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"symbol": "PERP_ETH_USDC",
"limit": 100
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| symbol | string | No | — | Market filter. |
| limit | int | No | 100; 1–500 | Maximum rows. |
| cursor | string | No | — | Opaque pagination cursor. |
Each row includes order_id, symbol, side, type, price, quantity, total_executed_quantity, trigger_price, trigger_status, status, reduce_only, created_time, and updated_time. order_id is a 64-bit integer encoded as a string. side is BUY, SELL, or BOTH. price can be null for market orders or trigger orders without a limit price. Algorithmic orders may include trigger_price, trigger_status (PENDING, TRIGGERED, or FAILED), and reduce_only; ordinary orders have these fields as null. The status returned by this query is always OPEN.
Rows are ordered by created_time descending and then order_id descending. The cursor continues from that ordering by comparing the timestamp and ID lexicographically; pass data.next_cursor unchanged.
Order status
Looks up one order by ID across both live and archived order data and includes algorithmic-order details when available. Weight: 5; one result, no pagination.
{
"type": "orderStatus",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"order_id": 123456789,
"broker_id": "pangoperps",
"account_id": "0xabc..."
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address; scopes the lookup to one user. Omitting it makes the lookup slower. |
| order_id | int64 | Yes | Order identifier. Missing value returns MISSING_PARAM. |
| broker_id, account_id | string | No | Optional account filters. |
The returned order includes the standard order fields such as order_id, symbol, side, type, price, quantity, total_executed_quantity, average_executed_price, trigger_price, status, total_fee, fee_asset, realized_pnl, reduce_only, created_time, and updated_time. Status can be PENDING_NEW, NEW, PARTIAL_FILLED, FILLED, PENDING_CANCEL, CANCELLED, REJECTED, or REPLACED. average_executed_price is null for live orders and a decimal for archived orders. total_fee and fee_asset are null for live orders. Algorithmic orders may have trigger_price. If the order is not in either data store, the API returns ORDER_NOT_FOUND (404).
Portfolio
Returns daily account-value and cumulative-PnL snapshots aligned to UTC days. Weight: 5. Use accountState for current collateral and unrealized PnL.
{
"type": "portfolio",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"interval": "1d",
"start_time": 1712000000000,
"end_time": 1715000000000,
"limit": 90
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| interval | string | No | 1d | Only 1d is supported; another value returns INVALID_PARAM. |
| start_time | int64 | No | end_time - 90d | Start time in milliseconds. |
| end_time | int64 | No | now | End time in milliseconds. |
| limit | int | No | 90; 1–365 | Maximum daily snapshots. |
| cursor | string | No | — | Opaque pagination cursor. |
Each data.rows[] item has account_value, cumulative_pnl, and timestamp. Rows are ordered by timestamp descending. Account value is the daily collateral snapshot (holdings plus frozen balance plus unrealized PnL); cumulative PnL is the account-value change from the earliest day in the returned window. The timestamp is the UTC-day-aligned snapshot time in milliseconds. interval values other than 1d and limits outside 1–365 return INVALID_PARAM. The response is paginated with data.next_cursor.
Position context
Returns one market's position (if any), open orders for that market, a market snapshot, and account risk figures. The component lookups run in parallel. Weight: 2.
{
"type": "positionContext",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"symbol": "PERP_BTC_USDC",
"broker_id": "pangoperps",
"account_id": "0xabc..."
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Wallet address. |
| symbol | string | Yes | Market symbol. |
| broker_id | string | No | Optional broker filter. |
| account_id | string | No | Optional account filter. If omitted, the primary account is the one with the highest account value, with a main account breaking ties. |
data contains position, open_orders[], market, and account_summary. The position has the same shape as an accountState.positions[] item and is null if the account has no position in that market. Open orders are already filtered to the requested symbol. The market object can be null if the symbol is absent from the latest market summary. The account summary contains free_collateral and margin_ratio, and can be null if the address is not found. This combined query is equivalent to requesting accountState, symbol-filtered openOrders, and marketSummary separately, but has a lower weight. Individual sections may have different freshness.
Trades
Returns executed fills for a wallet. The query combines real-time fills from the latest 24 hours with older archived history and uses a cursor to continue across both sources. Weight: 5.
{
"type": "trades",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"symbol": "PERP_ETH_USDC",
"start_time": 1714000000000,
"end_time": 1715000000000,
"limit": 200
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| symbol | string | No | — | Market filter. |
| start_time | int64 | No | — | Start of the requested window, in milliseconds. |
| end_time | int64 | No | If start_time is set, defaults to now | End of the requested window, in milliseconds. |
| limit | int | No | 100; 1–1000 without a time range, 1–2000 with one | Maximum rows. |
| cursor | string | No | — | Opaque cursor that includes the data source. |
Rows contain id, order_id, symbol, side, executed_price, executed_quantity, fee, fee_asset, is_maker, realized_pnl, and executed_timestamp. IDs are strings; order_id may be null for orphaned or liquidation fills. is_maker is a boolean. realized_pnl may be null for fills older than 24 hours because the archive does not retain that field.
The live interval covers [max(start_time, now - 24h), end_time]; archived data covers [start_time, min(end_time, now - 24h - 1ms)]. Pagination remains continuous across that boundary. Pass the returned cursor back unchanged. Recent data (within 24 hours) is fresher than archived results; older history is refreshed about hourly.
Deposits and withdrawals
Returns deposit and withdrawal transaction history for an address, sorted by transaction ID descending. Weight: 5.
{
"type": "userDepositsWithdrawals",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"side": "deposit",
"token": "USDC",
"limit": 100
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| side | string | No | — | deposit or withdraw; case-insensitive. Other values return INVALID_PARAM. |
| token | string | No | — | Token filter, for example USDC. |
| start_time, end_time | int64 | No | — | Time-window bounds in milliseconds. |
| limit | int | No | 100; 1–500 | Maximum rows. |
| cursor | string | No | — | Opaque pagination cursor. |
Each row contains id, token, side, amount, fee, chain_id, tx_id, status, and created_time. The transaction ID is returned as a string; chain_id is the EVM chain ID, also represented as a string; tx_id is the on-chain transaction hash. Status values include SUCCESS, PENDING, and FAILED. created_time is milliseconds. Results are paginated with data.next_cursor.
Whale context
Returns an address research bundle with account details, open positions, and recent fills. The component lookups run in parallel and degrade independently if a component is unavailable. Weight: 3.
{
"type": "whaleContext",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"broker_id": "pangoperps",
"recent_trades_limit": 20
}| Field | Type | Required | Default / limits | Description |
|---|---|---|---|---|
| address | string | Yes | — | Wallet address. |
| broker_id, account_id | string | No | — | Optional account filters. |
| recent_trades_limit | int | No | 20; clamped to 1–50 | Maximum recent fills to include. |
data contains account, positions[], and recent_trades[]. The account is a subset of accountState and can be null if no account resolves. Positions follow the accountState.positions[] format; recent fills follow the trades row format. If an individual component fails, its data may be null or an empty array while the overall request still succeeds.