Skip to main content

Spot Transfer

Type: SESSION · Weight: — (not on the /api/v3 rate limiter)

Status: Implemented.

POST /v1/spot/transfer

Move balance between the funding account of an exchange wallet session (the perpetuals account) and the spot account of the session's Canton party. Authenticated by the wallet-session bearer token, like /v1/wallet/*; there is no X-MBX-APIKEY / signature. The spot side is the same deterministic account (UUIDv5("rocky-spot:" + party)) that session-key issues keys for, so funds moved here appear in GET /api/v3/account under that party's session key.

Only CUSD can be transferred. Wallet-funded (enrolled) accounts cannot use this endpoint at all once on-chain settlement is active — their wallet is the only funding source.

Request — JSON body

POST /v1/spot/transfer
Authorization: Bearer <exchange wallet session token>
Content-Type: application/json

{ "asset": "CUSD", "amount": "12.5", "direction": "toSpot" }
FieldTypeRequiredNotes
assetstringyesCUSD (the alias USDC is accepted and mapped to CUSD). Case-insensitive. Any other asset → 400.
amountstringyesPositive decimal.
directionstringyestoSpot (funding → spot) or toFunding (spot → funding). Case-insensitive; TO_SPOT / FUNDING_TO_SPOT and TO_FUNDING / SPOT_TO_FUNDING are also accepted.

Response — 200 (values illustrative)

{
"asset": "CUSD",
"direction": "toSpot",
"amount": "12.5",
"fundingAvailable": "987.5",
"spotFree": "112.5"
}
FieldTypeNotes
assetstringAlways CUSD.
directionstringNormalized to toSpot or toFunding.
amountstringThe amount moved, as parsed.
fundingAvailablestringFunding-account available balance after the transfer.
spotFreestringSpot free balance of CUSD after the transfer.

Wallet-funded gates (active only once on-chain settlement is enabled for the venue; see On-chain Settlement)

AccounttoSpottoFunding
Enrolled (wallet-funded)rejectedrejected
Party-bound, not yet enrolledrejectedallowed (so a legacy internal balance can still be cleared)
Not party-boundallowedallowed

Errors — body is { "error": "<message>" }, not the {code,msg} envelope

HTTPerror / cause
400amount must be a positive decimal; only CUSD can be transferred between contract and spot accounts; unknown transfer direction: …; body not valid JSON; or the ledger rejected an argument.
401missing bearer token / invalid session.
403session has no Canton party; connect a wallet first.
422Wallet-funded account: fund via your Canton wallet; internal transfer is disabled. (the gate table above); or the ledger reported a precondition failure such as insufficient balance (its message is passed through).
500spot transfer failed; try again.