Wallet balances
Per-wallet token balances with optional USD valuation via SDP.
GET /v1/payments/wallets/{walletId}/balances returns a custody wallet's native SOL balance and every SPL token it holds, with raw and human-readable amounts, decimals, and a USD valuation where SDP has a price. SOL always comes first, as token: "SOL" with mint: "So11111111111111111111111111111111111111112". Token accounts with a zero balance are left out.
Request
walletId is the provider wallet ID: the walletId field from GET /v1/wallets, not the wallet's id (cwlt_…) or its address. The request needs an API key with wallets.read; a key limited to selected wallets reads only those.
If SDP can't read the SOL balance or any token balance, the request returns 503 instead of partial or zero balances. To read state no older than a slot you already saw, pass minimumSlot; the response echoes it in data.balanceReadContext.minimumSlot.
Response shape
The payload sits in the standard data / meta envelope, with the balances in data.walletBalances.balances:
Per-balance fields:
| Field | Notes |
|---|---|
token | Token symbol if known, otherwise the onchain mint. |
mint | Onchain mint address. |
amount | Raw amount in the smallest unit (a string, to preserve precision). |
uiAmount | Human-readable decimal string: amount / 10^decimals. |
decimals | The token's decimal count. |
usdPrice | Per-token USD price; omitted when no price is available. |
usdValue | Total USD value (usdPrice * uiAmount); omitted when no price is available. |
confidential | Reserved for confidential transfer balances; absent for standard balances. |
Use cases
- Account dashboards: show a custody wallet's contents to its operator.
- Pre-transfer balance checks: confirm a wallet holds enough of a token before you start a payout batch.
- Treasury accounting: take periodic snapshots into an internal ledger.
Pricing freshness
SDP prices balances only on mainnet. In a sandbox project on devnet, usdPrice and usdValue are always absent.
usdPrice is a display estimate from Tokens.xyz. SDP caches each price for up to 60 seconds. Some source snapshots refresh hourly; SDP omits snapshots older than two hours or without a timestamp. The snapshot timestamp doesn't prove when its underlying price was observed.
Use an executable quote for a trade and an independently verified valuation for accounting. The onchain amount and uiAmount remain the balance values. When pricing is unavailable, usdPrice and usdValue are absent: the omission means "unknown," not "$0.00."
Compared with onchain RPC
You can also list SPL token balances by calling getTokenAccountsByOwner on a Solana RPC node and decoding the token-account data. Use SDP's balances endpoint for:
- Token resolution: SDP resolves the mint to a symbol when it knows one; raw RPC returns mints only.
- USD pricing: RPC has no prices.
- One fewer dependency: no separate RPC integration when you already call SDP.
Go to RPC directly for:
- State at an exact slot: for an audit that needs the wallet as of one slot. SDP's
minimumSlotsets only a lower bound. - Confidential transfer balances: full extension support is RPC-side.
- Latency-sensitive paths: RPC is one hop closer to the cluster.
Related
- Payouts and disbursements: check balances before running a batch.
- Create a wallet: provision the wallets whose balances this endpoint reports.