Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Funding

Your money is held by the settlement contract, not by the exchange (see Custody). You deposit by calling the contract, and you withdraw by asking the exchange for a signed withdrawal and submitting it to the contract yourself.
The contract's address, the USDC token's address and the chain are at GET /v1/config.

Deposit

  1. Approve USDC
    Call approve(settlement, amount) on the USDC token. Skip this if you use depositWithPermit.
  2. Deposit
    Call deposit(amount) on the settlement contract, with amount in micro-USDC. Or call depositWithPermit(amount, deadline, v, r, s) with an EIP-2612 permit to approve and deposit in one transaction.
  3. Wait for the credit
    The exchange credits the deposit once its block reaches the chain's safe tag. Your first deposit opens your account. Watch for a funds event on your WebSocket account: channel, or poll GET /v1/account/{addr} until known is true and freeCash includes it.
TypeScript (viem)
import { parseAbi } from 'viem' const erc20 = parseAbi(['function approve(address spender, uint256 amount) returns (bool)']) const settlement = parseAbi(['function deposit(uint256 amount)']) const amount = 1_000_000_000n // $1,000 await wallet.writeContract({ address: config.usdc, abi: erc20, functionName: 'approve', args: [config.settlement, amount] }) await wallet.writeContract({ address: config.settlement, abi: settlement, functionName: 'deposit', args: [amount] })

Withdraw

  1. Request it
    Sign a WithdrawalRequest(user, amount, nonce) with the account's own key and send it to POST /v1/withdraw. The exchange debits your free cash at once.
  2. Collect the signed withdrawal
    The answer carries the exchange's signed withdrawal and its signature. If it says "pending": true, fetch it from GET /v1/withdrawals/{user} in a moment.
  3. Submit it
    Call withdraw(withdrawal, signature) on the settlement contract from your account's address. The contract pays you once it has executed your fills up to the withdrawal's afterFill, before its deadline.
TypeScript (viem)
const settlement = parseAbi([ 'function withdraw((address user, address to, uint128 amount, uint64 nonce, uint64 deadline, uint64 afterFill) wd, bytes sig)', ]) const { withdrawal: w, signature } = answer await wallet.writeContract({ address: config.settlement, abi: settlement, functionName: 'withdraw', args: [{ ...w, amount: BigInt(w.amount), nonce: BigInt(w.nonce), deadline: BigInt(w.deadline), afterFill: BigInt(w.afterFill) }, signature], })
Withdrawals are paid in the order the exchange signed them: submit an earlier one before a later one.
If the contract reverts with NotYetSettled, it has not yet executed every fill of yours before the withdrawal. Try again shortly.

Withdrawing without the exchange

If the exchange does not answer, call requestForcedWithdrawal(amount) on the contract. The exchange must cancel your orders and pay you; if it does not within the contract's forceWindow, anyone can freeze your account and you withdraw with escapeWithdraw(). Custody has the details.