/api/v1/trading: deposit adds collateral to a portfolio, withdraw takes it off the exchange, and transfer rebalances cash between portfolios without leaving. All three quote size in CentiCents, all three return a RequestAck, and a 200 OK can still be a rejection. For the units and balance model behind these moves, see collateral and cash.
Before you start
- Cash is USDC only, in CentiCents on writes:
1 CentiCent = 0.0001 USDC, so1,000 USDCissize = 10000000(1000 × 10000).sizeis a signed 64-bit integer. Balances read back as USDC decimal strings, never integers. - Every body is signed. You POST a
Base64SignedPayloadenvelope; the decoded bytes are the schema below. See signed payloads for the byte layout and signing procedure. - Branch on the ack. A signed write returns
{ status, processed_at_ns }.status = request_completedmeans accepted; anyrejected_*value means the move did not happen. Read the status — do not infer success from the HTTP code.
Deposit
Add USDC collateral to one portfolio.| Endpoint | POST /api/v1/trading/deposit |
| Auth | session-key signed body |
| Decoded body | DepositCash (request_type = 5) |
The receiving portfolio, as an
account_id / subaccount_index / portfolio_index triple.Cash to add, in CentiCents.
10000000 deposits 1,000 USDC.DepositSpot request type is rejected with 400; only USDC cash deposit is live.
Withdraw
Remove USDC collateral from a portfolio. The body and signing are identical to a deposit, but the exchange holds withdrawals to a higher bar.| Endpoint | POST /api/v1/trading/withdraw |
| Auth | admin-rooted session-key signed body |
| Decoded body | WithdrawCash (request_type = 7) |
DepositCash: a portfolio_id triple (the source) and size in CentiCents.
Spot withdrawal is not available. A WithdrawSpot request type is rejected with 400; only USDC cash withdrawal is live.
Transfer
Move USDC cash between portfolios without an external deposit or withdrawal. Both variants hitPOST /api/v1/trading/transfer; the request_type in the signed header selects which one.
- Intra-account
- Inter-account
Move cash between two portfolios under one account. The shared
Fields:
account_id is carried once, which is why this variant is cheaper on the wire than encoding two full triples.| Decoded body | IntraAccountCashTransfer (request_type = 32) |
| Auth | session-key signed body |
account_id, from_subaccount_index, from_portfolio_index, to_subaccount_index, to_portfolio_index, and size (CentiCents). Use this to fund an isolated-margin portfolio from your main one without leaving the exchange.status = rejected_self_transfer. Set distinct from/to portfolios.
Read the ack
Every one of these moves returns the same shape on200:
request_completed on acceptance. A rejected_* value (for example rejected_invalid_portfolio_id, rejected_unauthorized, rejected_self_transfer) means the cash did not move — the HTTP code is still 200.Exchange processing time, nanoseconds since the Unix epoch.
application/problem+json (RFC 9457) carrying a stable code. Branch on code, not on the human-readable detail. The error model lists both surfaces.
Confirm the move
Re-read the affected balances after arequest_completed. GET /api/v1/portfolio/balance returns one portfolio’s free cash as a USDC string; GET /api/v1/portfolio/cash_balances returns one balance per portfolio. Both authenticate with a read credential.
To fund a portfolio and place your first order end to end, follow the quickstart.