V2 Integrator API
Prepare Withdrawal Authorization (Stage 1)
Stage 1 of the two-stage withdrawal flow — returns an EIP-712 typed-data envelope for the end-user to sign in their wallet.
POST
Stage 1 of the two-stage withdrawal flow. Validates the request, checks
live onchain balances, and returns an EIP-712-typed authorization message
the end-user signs with their portfolio owner wallet. Stage 2
(
POST /v2/portfolios/{portfolioId}/withdraw) accepts the signed envelope
and dispatches the onchain transfer.
Wallet addresses are exchanged as
CAIP-10 account identifiers.
recipientAccountId uses the chain-bound EVM form
eip155:<chainId>:<address> — a withdrawal always goes to one address on one
specific chain. Only EVM recipients are supported today.
- Auth:
x-api-keyheader (required) - Scope:
portfolios:withdraw
authorizationId (= the signed message.nonce) is the
idempotency anchor for the matching POST .../withdraw call. Stage 1
returns the full EIP-712 typed-data object at data.typedData — pass it
directly to signTypedData(data.typedData) in the user’s wallet. On stage
2 the integrator echoes back typedData.message as body.message
alongside the signature.
The authorization is valid for 10 minutes. If the user takes longer to
sign — or a balance check fails at stage 2 — restart the flow by calling
this endpoint again.
Chain-equivalence rule
Every asset’sassetId must be on the same chain as recipientAccountId. A
single authorization withdraws a set of assets from one chain to one
recipient on that chain. Multi-chain withdrawals require separate
authorizations per chain.
Signed EIP-712 domain
The returneddomain binds the signature to two things:
chainId— the EVM chain the assets and recipient live on. Required for ERC-1271 smart-wallet verification, which re-hashes the typed-data using the wallet’s ownchainId.verifyingContract— the smart account being debited on that chain. Scopes the signature to a specific smart account deployment.
domain, types, primaryType, and message
verbatim to signTypedData in the user’s wallet.
What the user sees in their wallet
When rendering the signature prompt, the wallet displays each field of the signed struct. Users seerecipientAccountId as a CAIP-10 string like
eip155:1:0x4444… — chain and address are visible together. They also see
portfolioId, assets (CAIP-19 asset ids + raw atomic amounts),
nonce, and expiresAt. Integrators SHOULD surface a decoded summary in
their own UI (asset symbols, human-readable amounts) so users can verify
the recipient and amounts before approving.
Common error responses:
400 API_210 INSUFFICIENT_BALANCE— live balance belowamountRawfor at least one asset.400 API_211 INVALID_RECIPIENT— zero address, smart account self-transfer, or non-EVM namespace.400 API_212 DUPLICATE_WITHDRAW_ASSET— two or more assets inassetsshare the sameassetId.400 API_213 WITHDRAWAL_CHAIN_MISMATCH— at least one asset is on a different chain thanrecipientAccountId.400 API_215 PORTFOLIO_HAS_NO_VAULT_ON_CHAIN— portfolio has no smart account deployed on the recipient’s chain.400when the request body is otherwise invalid (schema errors).401whenx-api-keyheader is missing or the key is invalid.403when the API key lacks theportfolios:withdrawscope.404 API_200 PORTFOLIO_NOT_FOUND—portfolioIddoesn’t exist or belongs to a different tenant.500on unexpected server errors.