Skip to main content

Model

interface Balance {
  token: string;
  available: string;
  unsettled: string;
  locked: string;
  quarantined: string;
}
Total holdings = available + locked. unsettled and quarantined are reserved for future settlement modes and currently always zero.

Reading balances

GET /api/me/balances
X-Api-Key: ps_live_<keyId>_<secret>  # integrators — needs `portfolio:read`
Response:
{
  "walletAddress": "0x...",
  "balances": [
    { "token": "USDC", "available": "1248.22", "unsettled": "0", "locked": "75.00", "quarantined": "0" }
  ]
}

How locked moves

Eventavailablelocked
Order placed (BUY)-notional+notional
Order placed (SELL)00
Order cancelled+residual-residual
Trade executed (BUY)0-notional
Trade executed (SELL)+proceeds − fee0
Order rejected+full-full
Market resolved+residual-residual
Withdrawal requested-amount+amount
Withdrawal confirmed on-chain0-amount
Withdrawal rejected / reverted+amount-amount
SELL orders don’t move USDC balances — they encumber the outcome shares in vault_erc1155_locks instead. After you place a SELL, your available and locked USDC are unchanged; what does change is the available-to-promise outcome-share balance for the underlying token. When the SELL fills on-chain, USDC proceeds land in available per the table above.Inspect outcome-share balances via GET /api/me/positions. Each position row now carries three quantity fields:
  • quantity — mirror total (matches on-chain ERC-1155 balance). Use for “what do I own”.
  • availableQuantity — post-encumbrance, the amount you can currently sell or burn. Use for “what can I trade”.
  • encumberedQuantity — sum of open SELL orders’ unfilled quantity + active signedOp locks for the same (vault, tokenId). Always equals quantity − availableQuantity.

Append-only ledger

Every balance change is mirrored to an append-only balance_events table on the platform side. The conservation invariant holds for any (user, token): SUM(deltaAvailable) + SUM(deltaLocked) === current(available) + current(locked)
GET /api/me/balance-events returns the full append-only ledger for the authenticated wallet:
{
  "walletAddress": "0x...",
  "events": [
    {
      "id": "evt-...",
      "token": "USDC",
      "deltaAvailable": "-5.000000",
      "deltaLocked": "5.000000",
      "reason": "lock",
      "orderId": "ord-...",
      "tradeId": null,
      "createdAt": "2026-04-30T12:34:56.789Z"
    }
  ]
}
reason is one of lock, terminal_refund, withdrawal_confirmed, match_failed_refund, fee_settled, plus a few internal kinds. Pair with the WS vault_positions channel for live deltas — the REST endpoint is the canonical reconciliation source after a reconnect or any time you need to walk history.

Getting testnet balance

The faucet is not an endpoint on the partner API surface. Mint testnet USDC by calling the MockCollateral contract’s public mint(address, uint256) method directly, or use the operator-run faucet web UI: After minting, deposit normally via vault.depositERC20(...) — the faucet flow does not credit /api/me/balances until you deposit. See Environments — getting testnet USDC for the full step-by-step.