Withdrawal lifecycle
The typical flow is: preview -> initiate -> track -> complete.- Preview — call
withdrawal-previewto see what’s available and get a sourcing plan. - Initiate — call
withdrawto create the withdrawal. The system reserves liquidity and begins sourcing. - Track — poll the withdrawal or subscribe to webhooks. The withdrawal moves through statuses as positions unwind, funds bridge, and payouts execute.
- Complete — the withdrawal reaches
completedwhen all funds have been delivered.
Preview a withdrawal
Before initiating, preview what balance is available for a given destination.| Field | Required | Description |
|---|---|---|
destinationChain | Yes | Destination chain for the withdrawal |
amountUsd | No | Amount to preview as a number (max 6 decimal places). If omitted, previews the maximum available balance. |
| Field | Description |
|---|---|
amountUsd | The withdrawal amount previewed (equals the requested amount, or the max available if amountUsd was omitted) |
feeUsd | Fee for the withdrawal (currently always "0.000000") |
availableUsd | Unreserved liquidity available for this destination |
estimatedCompletionTime | Estimated end-to-end completion time as an ISO 8601 duration |
Initiate a withdrawal
| Field | Required | Description |
|---|---|---|
requestId | Yes | UUID v4 idempotency key |
destinationChain | Yes | Destination chain |
amountUsd | Yes | Amount as a number (max 6 decimal places) |
destinationAddress | Yes | Recipient address on the destination chain |
token field — USDC is the only supported withdrawal token.
Sandbox notes:
destinationChain: "ethereum"refers to Ethereum Sepolia in sandbox.- Solana withdrawals are not currently supported (the endpoint expects an EVM destination address).
List withdrawals
| Param | Description |
|---|---|
limit | Max items (default 50, max 200) |
cursor | Opaque cursor from nextCursor |
sort | Sort field (default createdAt) |
order | desc (default) or asc |
createdAtGte | ISO-8601 timestamp filter |
status | Repeatable status filter (e.g. status=processing&status=completed) |
Fetch a withdrawal
payouts array contains the individual payout legs of the withdrawal. Each payout represents a discrete transfer on a specific chain. Key fields:
| Field | Description |
|---|---|
yieldSourceId | Yield source identifier for the payout leg |
status | Payout leg status (see complete list below) |
turnkeyActivityId | Turnkey signing activity ID (only present while status is pending_customer_approval; null otherwise) |
approvalRequestedAt | When customer approval was requested (only present while status is pending_customer_approval; null otherwise) |
approvalValidBefore | ISO-8601 deadline for the approval (only present while status is pending_customer_approval; null otherwise) |
amount | Payout amount in token units (number) |
token | Token being transferred (e.g. usdc) |
chain | Chain the payout executes on |
txHash | Onchain transaction hash (populated after broadcast) |
txHash is a convenience field extracted from the primary completed payout.
Payout statuses
Each payout leg moves through the following statuses:| Status | Terminal | Meaning |
|---|---|---|
planning | No | Payout leg is being planned (sourcing route, computing amounts) |
processing | No | Payout is actively being processed (unwinding position, bridging) |
pending_customer_approval | No | Awaiting customer signature via Turnkey (turnkeyActivityId, approvalRequestedAt, and approvalValidBefore are populated) |
pending_broadcast | No | Signed transaction is queued for onchain broadcast |
broadcasted | No | Transaction has been broadcast; awaiting confirmation |
completed | Yes | Payout delivered successfully; txHash is populated |
failed | Yes | Payout failed; see failureReason |
cancelled | Yes | Payout was cancelled (e.g. parent withdrawal cancelled) |
skipped | Yes | Payout leg was skipped (e.g. zero-amount leg after partial completion) |
Withdrawal statuses
Withdrawals move through five statuses:| Status | Meaning |
|---|---|
pending | Accepted and reserved; processing hasn’t started yet |
processing | Unwinding positions, bridging, or delivering funds |
completed | Terminal: funds delivered to destination address |
failed | Terminal: withdrawal failed |
cancelled | Terminal: withdrawal was cancelled |
Cancel a withdrawal
Cancel an in-progress withdrawal:completed rather than cancelled.
Timing expectations
Withdrawal time depends on which yield positions need to unwind and whether cross-chain bridging is required.| Position | Unwind time | Notes |
|---|---|---|
| Cash (USDC) | Instant | No unwind needed |
resolv-lp | Up to 24h (PT24H) | Async Resolv exit window |
syrup-usdc | Up to 24h (PT24H) | ERC-4626 redemption on Ethereum with asynchronous withdrawal window |
usdz | Instant (PT0H) | Convert to USDC on Arbitrum |
Withdrawal webhooks
Subscribe toportfolio_wallet.withdrawal.status_changed for real-time withdrawal tracking.
See Webhooks for registration and payload details.
Bridge domains reference
A bridge domain is a hard boundary for where liquidity can come from. The withdrawal engine never crosses bridge domain boundaries.USDC unified (CCTP)
USDC on CCTP-supported chains forms a singleusdc:unified domain:
- Arbitrum, Base, Ethereum, Polygon, Solana
USDT (always per-chain)
USDT has no cross-chain unification:usdt:arbitrum,usdt:base,usdt:ethereum,usdt:polygon,usdt:solana
Default (per-chain)
All other tokens are per-chain:dai:ethereum,usdz:arbitrum, etc.