Submit a withdrawal request

Submits a withdrawal request transaction signed by the customer's wallet.

POST/v1/earn/external-wallet/withdrawal-requests

SDP checks every signature against the exact built message, records the request before broadcast, then sends it. Idempotency-Key is required: a retry with the same key returns the original request, and each built transaction can be submitted once. Reusing a key with a different body, or submitting one build under a second key, returns 409 CONFLICT. An expired build can still be submitted late. If its reservation was released or replaced, SDP accepts it only once the exact signed transaction is finalized as successful, so after a 409 CONFLICT retry the same bytes and key until that shows. A late operator redemption whose original cycle already closed is refused for operator reconciliation, so it cannot claim a newer request at the same address. A transaction that recovery finds finalized as failed returns 400 TRANSACTION_FAILED; build a new one. A recovery RPC outage returns 503 PROVIDER_UNAVAILABLE: retry the original bytes and key. An unresolved 16-signature history window returns 503 and needs support to reconcile. An expired operator redemption build whose creation history is unavailable also returns 503: keep and retry the original signed intent rather than signing a replacement.

Requires an API key with the earn.execute action.

Headers

  • x-project-id · string · min length 1 · example prj_example

    Required for dashboard sessions. API keys use their assigned project.

  • Idempotency-Key · string · required · pattern ^[\x20-\x7e]{1,255}$ · example idempotency_example_12345

    Idempotency key for safely retrying mutating requests. 1-255 printable ASCII characters; echoed back on the response.

Request body

application/json · required

Submit the signed bytes back. Requires the Idempotency-Key header; a retry with the same key resolves the original movement or withdrawal request instead of acting twice.

  • transactionId · string · required · min length 1 · max length 128 · example earn_external_wallet_transaction_e7a88258-1d19-48f3-8d0e-81fefa4bf3b3

    The built transaction being submitted; single-use.

  • signedTransaction · string · required · min length 1 · max length 1700 · pattern ^[A-Za-z0-9+/]+={0,2}$ · example AUyx/sEc49/1l6jxo3nbViPAIUqdrXCo8Qx5SfDvIbtUI0zex3Bi6Cyhhn1QTVU8zWDzXTRyIX2aCmq9v7yk5AOAAQABAvSV602SJ67iQCUGLwHzVtPnlMbZqL79wnV/nb+Mi9SJBUpTWpkpIQZNJOhxYNo4fHw1td28kruB5B+oQEEFRI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAtzZHAtZXhhbXBsZQA=

    Base64 wire bytes of the signed transaction. They must be byte-for-byte the built message with only signatures added.

Responses

  • 200 The recorded withdrawal request

    • data · object · required

      • withdrawalRequest · object · required

        Any of:

        • mechanism: "solverQueue"

          • withdrawalRequestId · string · required · example earn_vault_withdrawal_request_3c905ad2-c92c-4258-9675-1899c41569b9

          • positionId · string · required · example earn_position_2f8b6b04-7147-487e-b760-b1caa4fbcb8b

          • provider · string · required · example veda

          • providerReference · string · required

            The strategy's onchain address.

          • ownerAddress · string · required · example 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM

            The customer's wallet address.

          • requestAddress · string · required

            Provider request account address.

          • status · string · required · one of creating, pending, fulfillable, expiredCancelable, cancelling, fulfilled, cancelled, closedOrUnknown, failed

            The request's status. Only fulfilled, cancelled and failed are final. Keep tracking every other status, closedOrUnknown included: SDP resolves it from a finalized close event.

          • assetMint · string · required · min length 32 · max length 44 · pattern ^[1-9A-HJ-NP-Za-km-z]{32,44}$ · example 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo

            Base58 Solana mint address.

          • shareMint · string · required · min length 32 · max length 44 · pattern ^[1-9A-HJ-NP-Za-km-z]{32,44}$ · example 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo

            Base58 Solana mint address.

          • shares · string · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            Positive decimal string with at least one non-zero digit; never a float.

          • quotedAssets · string · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            Expected payout at request creation, in assetMint units. Not a settled amount.

          • shareDecimals · integer · required · min 0 · max 38

          • assetDecimals · integer · required · min 0 · max 38

          • nonce · string | null · required

          • creationTimestamp · string | null · required · pattern ^\d+$

          • creationSignature · string | null · required

            The request-creation transaction. Its confirmation does not prove a payout.

          • cancelSignature · string | null · required

            The cancellation transaction, once one is submitted.

          • closingSignature · string | null · required

            Provider-authenticated fulfillment or cancellation transaction, when known.

          • assetsPaid · string | null · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            The payout SDP observed at fulfillment, in assetMint units; null until then.

          • failureReason · string | null · required

          • fulfilledAt · string | null · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • cancelledAt · string | null · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • createdAt · string · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • updatedAt · string · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • replayed · boolean

          • mechanism · string · required · always solverQueue

          • intermediateMint · any · required

          • intermediateAmount · any · required

          • discountBps · integer · required · min 0 · max 10000

          • maturityTimestamp · string · required · pattern ^\d+$

          • deadlineTimestamp · string · required · pattern ^\d+$

        • mechanism: "operatorRedemption"

          • withdrawalRequestId · string · required · example earn_vault_withdrawal_request_3c905ad2-c92c-4258-9675-1899c41569b9

          • positionId · string · required · example earn_position_2f8b6b04-7147-487e-b760-b1caa4fbcb8b

          • provider · string · required · example veda

          • providerReference · string · required

            The strategy's onchain address.

          • ownerAddress · string · required · example 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM

            The customer's wallet address.

          • requestAddress · string · required

            Provider request account address.

          • status · string · required · one of creating, pending, fulfillable, expiredCancelable, cancelling, fulfilled, cancelled, closedOrUnknown, failed

            The request's status. Only fulfilled, cancelled and failed are final. Keep tracking every other status, closedOrUnknown included: SDP resolves it from a finalized close event.

          • assetMint · string · required · min length 32 · max length 44 · pattern ^[1-9A-HJ-NP-Za-km-z]{32,44}$ · example 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo

            Base58 Solana mint address.

          • shareMint · string · required · min length 32 · max length 44 · pattern ^[1-9A-HJ-NP-Za-km-z]{32,44}$ · example 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo

            Base58 Solana mint address.

          • shares · string · required · max length 128 · pattern ^\d+(\.\d+)?$ · example 10

            Position shares the request burns, in share units; "0" when it redeems intermediate the owner already holds.

          • quotedAssets · string · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            Expected payout at request creation, in assetMint units. Not a settled amount.

          • shareDecimals · integer · required · min 0 · max 38

          • assetDecimals · integer · required · min 0 · max 38

          • nonce · string | null · required

          • creationTimestamp · string | null · required · pattern ^\d+$

          • creationSignature · string | null · required

            The request-creation transaction. Its confirmation does not prove a payout.

          • cancelSignature · string | null · required

            The cancellation transaction, once one is submitted.

          • closingSignature · string | null · required

            Provider-authenticated fulfillment or cancellation transaction, when known.

          • assetsPaid · string | null · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            The payout SDP observed at fulfillment, in assetMint units; null until then.

          • failureReason · string | null · required

          • fulfilledAt · string | null · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • cancelledAt · string | null · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • createdAt · string · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • updatedAt · string · required · format date-time · example 2025-01-01T00:00:00.000Z

            ISO 8601 timestamp.

          • replayed · boolean

          • mechanism · string · required · always operatorRedemption

          • intermediateMint · string · required · min length 32 · max length 44 · pattern ^[1-9A-HJ-NP-Za-km-z]{32,44}$ · example 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo

            Base58 Solana mint address.

          • intermediateAmount · string · required · max length 128 · pattern ^(?=.*[1-9])\d+(\.\d+)?$ · example 25

            Positive decimal string with at least one non-zero digit; never a float.

          • discountBps · any · required

          • maturityTimestamp · any · required

          • deadlineTimestamp · any · required

    • meta · object · required

      Response metadata.

      • requestId · string · required · min length 1 · example req_example

        Request identifier for tracing.

      • timestamp · string · required · format date-time · example 2025-01-01T00:00:00.000Z

        ISO 8601 timestamp.

  • 400 Bad Request

    • error · object · required

      Standard error payload.

      • code · string · required

        Machine-readable error code.

      • message · string · required

        Human-readable error message.

      • details · object

        Optional error details for debugging.

        • * · any
    • meta · object

      • requestId · string · min length 1 · example req_example

        Request identifier for tracing.

  • 401 Unauthorized

    Same fields as 400.

  • 403 Forbidden. Requires the earn.execute action: an API key must hold it (a module's manage or execute also covers its read), and a signed-in member's organization role must include it. Without it the error is INSUFFICIENT_PERMISSIONS and error.details.action names the action. Any other 403 names its own reason.

    Same fields as 400.

  • 404 Not Found

    Same fields as 400.

  • 409 Conflict

    Same fields as 400.

  • 429 Too Many Requests

    Same fields as 400.

  • 500 Internal Server Error

    Same fields as 400.

  • 503 Service Unavailable

    Same fields as 400.

Example request

IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST 'https://api-beta.solana.com/v1/earn/external-wallet/withdrawal-requests' \
  -H "Authorization: Bearer $SDP_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionId": "earn_external_wallet_withdrawal_request_transaction_54c50679-1b52-494d-84fa-106df66452ff",
    "signedTransaction": "AUyx/sEc49/1l6jxo3nbViPAIUqdrXCo8Qx5SfDvIbtUI0zex3Bi6Cyhhn1QTVU8zWDzXTRyIX2aCmq9v7yk5AOA"
  }'
// Reuse this key when you retry this request.
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://api-beta.solana.com/v1/earn/external-wallet/withdrawal-requests", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SDP_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "transactionId": "earn_external_wallet_withdrawal_request_transaction_54c50679-1b52-494d-84fa-106df66452ff",
    "signedTransaction": "AUyx/sEc49/1l6jxo3nbViPAIUqdrXCo8Qx5SfDvIbtUI0zex3Bi6Cyhhn1QTVU8zWDzXTRyIX2aCmq9v7yk5AOA"
  })
});
import os, requests, uuid

# Reuse this key when you retry this request.
idempotency_key = str(uuid.uuid4())
r = requests.post("https://api-beta.solana.com/v1/earn/external-wallet/withdrawal-requests",
  headers={"Authorization": f"Bearer {os.environ['SDP_API_KEY']}", "Idempotency-Key": idempotency_key},
  json={
    "transactionId": "earn_external_wallet_withdrawal_request_transaction_54c50679-1b52-494d-84fa-106df66452ff",
    "signedTransaction": "AUyx/sEc49/1l6jxo3nbViPAIUqdrXCo8Qx5SfDvIbtUI0zex3Bi6Cyhhn1QTVU8zWDzXTRyIX2aCmq9v7yk5AOA"
  })

Example responses

JSON
{
  "data": {
    "withdrawalRequest": {
      "withdrawalRequestId": "earn_vault_withdrawal_request_3c905ad2-c92c-4258-9675-1899c41569b9",
      "positionId": "earn_position_0432ffeb-c574-4b11-80dc-a09defb68fcc",
      "provider": "veda",
      "providerReference": "3wbKP5UGLT7gAZBAsLjvPC1NbfnWKtT3Dq7cniMWkzfU",
      "ownerAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
      "requestAddress": "DKw4pYcvXNLs91RssedGFznWRpbvPttp2AAwNCG7fQRz",
      "status": "pending",
      "mechanism": "solverQueue",
      "assetMint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
      "shareMint": "CdV7pjj6WANsdasKsBvdKAn7qJL7cQ2Q3CJMBEe13WAV",
      "intermediateMint": null,
      "intermediateAmount": null,
      "shares": "15",
      "quotedAssets": "14.985",
      "shareDecimals": 6,
      "assetDecimals": 6,
      "discountBps": 10,
      "nonce": "0",
      "creationTimestamp": "1793987449",
      "maturityTimestamp": "1793991049",
      "deadlineTimestamp": "1793991109",
      "creationSignature": "3dhkSPLiQZQPXL96fWzMdWJtdbtAffkBKXw2xhsYbV3VNSnYrVAcdx1czsnLsE1ou4SvLecGdSYe4QpAuZdfjJAf",
      "cancelSignature": null,
      "closingSignature": null,
      "assetsPaid": null,
      "failureReason": null,
      "fulfilledAt": null,
      "cancelledAt": null,
      "createdAt": "2026-11-06T18:10:18.900Z",
      "updatedAt": "2026-11-06T18:26:00.379Z"
    }
  },
  "meta": {
    "requestId": "req_example",
    "timestamp": "2025-01-01T00:00:00.000Z"
  }
}
JSON
{
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "Missing action: earn.execute",
    "details": {
      "action": "earn.execute"
    }
  },
  "meta": {
    "requestId": "req_example"
  }
}

Error responses use the standard error shape.