Build a withdrawal transaction
Builds an unsigned withdrawal transaction for a position, for the customer's wallet to sign.
POST/
Withdrawals keep working after a provider stops taking deposits. Send minAmountOut when the strategy's withdrawalSlippage is not null, and omit it when null. A provider-order route may not support a preview: it places an order that pays out later, not an instant redemption.
Requires an API key with the earn.execute action.
Headers
-
x-project-id·string· min length 1 · exampleprj_exampleRequired for dashboard sessions. API keys use their assigned project.
Request body
application/json · required
Build one unsigned withdrawal transaction for a position. SDP reads the strategy and mints from the position.
-
positionId·string· required · min length 1 · max length 128 · exampleearn_position_2f8b6b04-7147-487e-b760-b1caa4fbcb8bThe position's ID, from the positions list or the deposit submit response.
-
redemptionMode·string· one ofstandard,instantThe redemption route to build:
standardqueues a provider-managed order for a later payout,instantis the provider's faster route but still waits for cross-chain delivery — chain confirmation alone is not payout, so treat the exit as complete only at the movement's verifieddeliveredoutcome. Defaults tostandard; a provider without the requested route refuses the build. -
shares·string· required · max length 128 · pattern^(?=.*[1-9])\d+(\.\d+)?$· example10Shares to redeem, decimal string in share units.
-
minAmountOut·string· max length 128 · pattern^(?=.*[1-9])\d+(\.\d+)?$· example19.98Withdrawal slippage floor: the minimum deposit-token amount to accept, as a decimal string. Derive it from the withdrawal preview's
assetsOutminus your tolerance. Required when the strategy'swithdrawalSlippageis not null; refused with 400 when it is null, because the transaction cannot enforce it. -
feePayer·string· min length 32 · max length 44 · pattern^[1-9A-HJ-NP-Za-km-z]{32,44}$· example3nMFwZXwY1s1M5s8vYAHqd4wGs4iSxXE4LRoUMMYqEgFPay for this transaction from a wallet your backend controls instead of the customer's. The named address becomes the fee payer: it pays the network fee, funds any share-account rent, and must sign alongside the customer. Co-sign on your backend before you submit. The build returns 400, naming the fee payer, when it cannot pay. Sending the customer's own address keeps the default: the customer pays and signs alone.
Responses
-
200Unsigned withdrawal transaction-
data·object· required-
transaction·object· requiredThe common fields of one built withdrawal transaction.
-
transactionId·string· required · exampleearn_external_wallet_transaction_e7a88258-1d19-48f3-8d0e-81fefa4bf3b3 -
transaction·string· requiredBase64 wire bytes of the unsigned transaction. Add every required signature without changing the message, then submit through SDP. The blockhash bounds when the network can first accept it; retain the original signed bytes for recovery.
-
lastValidBlockHeight·string· required · example361186610Last block height at which the network can first accept this transaction. This is a block height, not a slot or timestamp.
-
sponsored·boolean· required · examplefalseAlways false: SDP does not pay an external wallet's fees. The customer's wallet pays, or the
feePayeryou name. -
ownerAddress·string· required · example9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWMThe customer's wallet address.
-
feePayer·string· example3nMFwZXwY1s1M5s8vYAHqd4wGs4iSxXE4LRoUMMYqEgFThe
feePayeryour build request named. When present, the transaction needs the fee payer's signature as well as the customer's: co-sign on your backend before you submit, or the submit refuses it. When omitted, the customer signs alone and pays the fee. -
provider·string· required · examplekamino -
providerReference·string· required · example7uib8xGAwkaPz4ZGCA6t8sSEid5Yp9ty13PHUweTypxThe strategy's onchain address at the provider. It identifies the instrument; never send funds to it.
-
tokenMint·string· required · example4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU -
shareMint·string· required · examplehXm2xSRF5PLKGMrTvAWqKhR76MuJX5dAabeSChkjqu2 -
shares·string· required · max length 128 · pattern^(?=.*[1-9])\d+(\.\d+)?$· example25Positive decimal string with at least one non-zero digit; never a float.
-
minAmountOut·string | null· required · max length 128 · pattern^(?=.*[1-9])\d+(\.\d+)?$· example25The floor encoded in the transaction, or null when the request carried none.
-
positionId·string· required · exampleearn_position_2f8b6b04-7147-487e-b760-b1caa4fbcb8b
-
-
-
meta·object· requiredResponse metadata.
-
requestId·string· required · min length 1 · examplereq_exampleRequest identifier for tracing.
-
timestamp·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
-
-
400Bad Request-
error·object· requiredStandard error payload.
-
code·string· requiredMachine-readable error code.
-
message·string· requiredHuman-readable error message.
-
details·objectOptional error details for debugging.
*·any
-
-
meta·object-
requestId·string· min length 1 · examplereq_exampleRequest identifier for tracing.
-
-
-
401UnauthorizedSame fields as
400. -
403Forbidden. Requires theearn.executeaction: an API key must hold it (a module'smanageorexecutealso covers itsread), and a signed-in member's organization role must include it. Without it the error is INSUFFICIENT_PERMISSIONS anderror.details.actionnames the action. Any other 403 names its own reason.Same fields as
400. -
404Not FoundSame fields as
400. -
429Too Many RequestsSame fields as
400. -
500Internal Server ErrorSame fields as
400. -
501The provider does not support this operation.-
error·object· requiredStandard error payload.
-
code·string· required -
message·string· requiredHuman-readable error message.
-
details·objectOptional error details for debugging.
*·any
-
-
meta·object-
requestId·string· min length 1 · examplereq_exampleRequest identifier for tracing.
-
-
-
503Service UnavailableSame fields as
400.