Cash balance and buying power
Fetch cash balance and available-to-trade amounts with the SDK or HTTP API.
For progressive UI, read display cash with getFunding(..., { details: 'summary' })
and available cash independently with getTradingAvailability(userId)
(GET /v1/accounts/:externalUserId/wallet/trading-availability, wallet:read).
Use the shared account-state store to deduplicate
reads and manage freshness across screens. Its availableCash name maps to the
unchanged HTTP availableToTrade.formatted field.
The combined getFunding path remains supported for existing integrations.
There is no separate balance SDK package or organization-specific endpoint.
Before you start: a ready account and a server-side credential with
funding access enabled. Use the configured server client
and select externalUserId from your authenticated user's session, not an
unchecked browser parameter. HTTP examples omit signing headers.
Fetch cash and available to trade together
The compatible details: 'trading' path returns both
values; no separate cash request or deposit-instructions request is needed.
const result = await crisp.getFunding('example:user-123', { details: 'trading' });Illustrative response excerpt; identifiers and other funding fields are omitted:
{
"data": {
"balance": {
"baseUnit": "10000000",
"formatted": "10.0",
"decimals": 6,
"symbol": "pUSD"
},
"balanceStatus": "available",
"availableToTrade": {
"formatted": "7.500000",
"symbol": "pUSD"
},
"details": "trading"
}
}| UI value | SDK response field | Meaning |
|---|---|---|
| Cash balance | result.data.balance.formatted | On-chain pUSD held at the managed trading address; not the user's external wallet or total portfolio value |
| Exact cash base units | result.data.balance.baseUnit | Integer string; pUSD has six decimals, so 1000000 is 1 pUSD |
| Available to trade | result.data.availableToTrade.formatted | Executor-reported buying power after accounting for venue balance/allowance, resting BUY reservations and reserved trading fees |
In this example, the account holds 10 pUSD but only 7.5 pUSD is currently available for trading. Do not replace available buying power with the cash balance or calculate it by subtracting position value. Pending bridge deposits and unredeemed winning positions are not credited cash.
Fetch cash only
Use details: 'summary' for a header or cash-only portfolio display. It avoids
the executor buying-power read and Bridge instructions. If the order ticket
already fetched trading, reuse its cash value instead of making this second call.
const result = await crisp.getFunding('example:user-123', { details: 'summary' });details | Cash balance | Buying power | Deposit instructions |
|---|---|---|---|
summary | Requested | Not loaded; availableToTrade is always null | Not loaded |
trading | Requested | Requested | Not loaded |
full (default) | Requested | Requested | Requested |
Prefer an explicit detail level. Load full when opening the
deposit or withdrawal flow, not on every balance refresh.
In summary and trading, withdrawal.enabled: false with
availability: 'details_not_loaded' does not mean withdrawals are disabled for your organization.
Handle unavailable values without showing a false zero
A successful HTTP response can contain partial data:
balance: nullwithbalanceStatus: 'temporarily_unavailable'means the cash read failed.availableToTrade: nullmeans buying power was not loaded (summary) or its read failed (trading/full).- Cash and buying power are independent reads.
balanceStatusdescribes only cash; it does not tell you whether buying power is available. - A non-null
formatted: '0.000000'is an actual zero. Do not use||to replace it, or default missing data to zero.
For a completed trading request, extract display values without losing this distinction:
const cash = result.data.balance?.formatted ?? null;
const availableToTrade = result.data.availableToTrade?.formatted ?? null;
const cashLabel = cash === null ? 'Unavailable' : `${cash} pUSD`;
const buyingPowerLabel = availableToTrade === null
? 'Unavailable'
: `${availableToTrade} pUSD`;Keep amount strings intact; use decimal-safe arithmetic for financial calculations.
Cash formatted is a decimal string, not guaranteed to have six trailing digits.
availableToTrade.formatted is currently formatted to six decimal places and
has no separate base-unit field.
Refresh and place orders
Refresh in the background when the account changes, after deposits arrive,
after fills/cancellations/redemptions/withdrawals, and on relevant
realtime invalidations, including balance.updated.
Invalidate the previous user's values immediately when switching accounts.
On a refresh failure, label any retained value as stale and offer retry; do not
silently relabel old data as fresh or fall back from buying power to cash.
Buying power is a snapshot, not a reservation or a guarantee of acceptance. The executor rechecks funds when submitting. Use background order requirements for the selected market's fees, minimum and all-in cost. Do not blindly send the full buying-power value as a BUY amount: new-order fees may need additional room. SELL inputs are shares, not this cash amount.
Neither getFunding nor an order-requirements read is a mandatory extra request
before every click. Reuse the displayed snapshot while refreshing; the SDK's
order helpers retain their existing direct execution path.
Full response contract: getFunding.