Skip to main content
POST
Stage 2 of the two-stage withdrawal flow. Accepts the message object returned by stage 1 verbatim, plus the user’s signature over the authorization. Verifies the signature against the portfolio owner, re-checks live onchain balances, and dispatches the transfer onchain. body.message is the structured message from stage 1 — typedData.message for EVM portfolios, authorization.message for Solana portfolios (the shape is identical), including the liquidate flag. Echo it back verbatim: the signature was computed over these exact bytes. body.signature encoding depends on how the owner signed:
  • EVM (and Solana Model A, EVM-rooted): 0x… hex (EIP-712 / EIP-191 ECDSA; EVM also accepts ERC-1271 smart-contract-wallet signatures).
  • Solana Model B (Solana-rooted): base58 ed25519.
For Solana, Glider’s pooled agent executes the transfer out of the Swig sub-account and the paymaster sponsors the fee; the verified owner signature is the authorization. See stage 1 → Solana withdrawals.
  • Auth: x-api-key header (required)
  • Scope: portfolios:withdraw
Recipient: recipientAccountId may be any address the owner signs for (e.g. a user’s smart wallet), on both EVM and Solana — the recipient is bound into the owner-signed authorization, so any payout is explicitly authorized by the owner. A self-transfer to the smart account / Swig sub-account being debited is always rejected (400 API_211 INVALID_RECIPIENT).

Idempotency

Keyed on nonce (scoped to your API key). Retries with the same message + signature replay the cached 202 response. Retries with the same nonce but a different body return 409 IDEMPOTENCY_KEY_CONFLICT — fix the client, don’t retry. Two parallel requests with the same body: one proceeds, the other sees 409 IDEMPOTENCY_IN_PROGRESS — retry the identical body after 2–3 seconds. If stage 2 fails after accepting the request (e.g., a transient signature verification error, or balance drops below the requested amount between stages), the idempotency lock is released so the integrator can re-submit the same message + signature once the transient issue resolves.

Liquidation

When the signed message.liquidate is true, the authorized assets are swapped to the signed message.settlementAssetId settlement asset (USDC by default; USDT also allowed on EVM) and delivered to the recipient instead of being transferred as-is. The assets, settlement asset, and recipient must all reference the same chain; this flow does not perform cross-chain delivery or bridging. On Solana the swaps and the final delivery run as one engine operation inside the portfolio’s smart account. The returned operationId tracks the swap. Both liquidate and settlementAssetId are part of the signed message and cannot be changed here. A 400 API_219 WITHDRAW_AS_USDC_UNSUPPORTED_CHAIN is returned when the default USDC settlement asset is unavailable on the chain; a 400 API_221 UNSUPPORTED_SETTLEMENT_ASSET is returned when settlementAssetId is not an allowed settlement asset on the chain.

Polling for onchain status

The response returns operationId. Poll GET /v2/portfolios/{portfolioId}/operations/{operationId} until the operation reaches a terminal (completed / failed / cancelled) state.

Common error responses

  • 400 API_216 WITHDRAWAL_AUTHORIZATION_EXPIRED — signed authorization’s expiresAt is in the past. Restart the flow via stage 1.
  • 400 API_217 INVALID_WITHDRAWAL_SIGNATURE — signature does not recover to the portfolio owner. Almost always a client bug.
  • 400 API_210 INSUFFICIENT_BALANCE — balance dropped below amountRaw between stage 1 and stage 2. Restart stage 1 to issue a fresh authorization.
  • 400 API_214 WITHDRAWAL_PORTFOLIO_MISMATCHmessage.portfolioId doesn’t match the URL path.
  • 400 API_213 WITHDRAWAL_CHAIN_MISMATCH — at least one asset is on a different chain than recipientAccountId.
  • 400 API_215 PORTFOLIO_HAS_NO_VAULT_ON_CHAIN — portfolio has no smart account deployed on the recipient’s chain.
  • 400 API_219 WITHDRAW_AS_USDC_UNSUPPORTED_CHAINmessage.liquidate is true (with the default USDC settlement asset) but the recipient’s chain has no canonical USDC.
  • 400 API_221 UNSUPPORTED_SETTLEMENT_ASSETmessage.settlementAssetId is not an allowed settlement asset on the recipient’s chain (configured USDC or USDT for an EVM withdrawal, or USDC for a Solana withdrawal).
  • 400 API_212 DUPLICATE_WITHDRAW_ASSET — two or more assets in assets share the same assetId.
  • 400 API_218 UNSUPPORTED_WITHDRAW_ASSET — the requested asset cannot use the direct-transfer withdrawal path. For a redemption-required yield share, redeem through its registered yield source and then withdraw the underlying asset.
  • 400 API_211 INVALID_RECIPIENT — zero address, or a self-transfer to the smart account / Swig sub-account being debited.
  • 403 API_104 PERMISSION_DENIED — Solana withdrawal but the svm_b2b_api feature is not enabled for the tenant.
  • 404 API_200 PORTFOLIO_NOT_FOUNDportfolioId doesn’t exist or your API key cannot access it (can surface at stage 2 if the portfolio was archived/reassigned between stages).
  • 409 API_007 IDEMPOTENCY_IN_PROGRESS — another request with the same nonce is still running. Retry the identical body.
  • 409 API_008 IDEMPOTENCY_KEY_CONFLICT — nonce reused with a different body. Don’t retry; restart stage 1.
  • 503 API_506 SIGNATURE_VERIFIER_UNAVAILABLE — signature verification is temporarily unavailable. Safe to retry; the idempotency lock has been released.