Skip to main content

Request Withdrawal

Status: Implemented. Session-token endpoint; rejected with 403 for wallet-funded spot accounts, which withdraw by moving assets in their own wallet.

POST /v1/withdrawals

Submit a withdrawal of amount units of asset from the session user's spot wallet to the Canton party dest_user_handle_party.

Auth: Authorization: Bearer <session_token> (see place-order). The session must carry the withdraw permission and have a Canton party_id. The user is taken from the session — there is no user_id field.

Request

POST /v1/withdrawals
Authorization: Bearer <session_token>
Content-Type: application/json

{
"asset": "CC",
"amount": "10.0",
"dest_user_handle_party": "alice::1220abc...",
"idempotency_key": "ui-withdraw-1748275200"
}
FieldTypeRequiredNotes
assetstringyesCase-insensitive. Aliases: USDC / USDA / USDC-X → CUSD; AMULET / CANTONCOIN / CANTON_COIN → CC; CETH → cETH; USDCX → USDCx. Must be withdrawal-enabled in the asset registry.
amountstringyesDecimal > 0, at most the asset's registered number of decimal places.
dest_user_handle_partystringnoDefaults to the session's own party_id when omitted or blank.
idempotency_keystringyesNon-empty. Re-sending the same key with a different payload is rejected by the ledger.

Withdrawal fee: quoted server-side at request time. Stablecoins (CUSD, USDCx, USX, USDC.B) pay a fixed 1 of the same asset; CBTC / cETH / CC pay the equivalent of 1 USD in the withdrawn asset (oracle price, rounded up to the asset's decimals; fee_quote_price / fee_quote_ts_ms are then present). Preview it with GET /v1/withdrawals/quote?asset=... (same auth).

Response — 200

{
"withdrawal_request_id": "8c9a1f2e-7b6d-5c4a-3b2c-1d0e9f8a7b6c",
"withdrawal_id": "8c9a1f2e-7b6d-5c4a-3b2c-1d0e9f8a7b6c",
"status": "submitted",
"asset": "CC",
"amount": "10.0",
"fee_asset": "CC",
"fee_wallet_symbol": "CC",
"fee_amount": "0.0000142858",
"fee_quote_price": "70000",
"fee_quote_ts_ms": 1748275200000,
"destination_party": "alice::1220abc..."
}

withdrawal_request_id and withdrawal_id are the same hyphenated UUID. status is always "submitted" in this response; poll GET /v1/withdrawals/{wid} for the live state.

Errors (plain-text body): 400 validation (asset is required, unsupported withdrawal asset, amount must be positive, amount supports at most N decimal places, withdrawal destination is required, idempotency_key is required, session does not have party_id), 401 missing/invalid session token, 403 withdrawal permission denied or wallet-funded account (spot withdrawals disabled), 409 ledger precondition failed (e.g. insufficient spot balance), 502 other ledger/trading errors (including an idempotency_key reused with a different payload), 503 fee quote unavailable/stale or eligibility check unavailable, 504 request timed out (15 s).