> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getplu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Withdrawal

> Request a USDC withdrawal from your partner wallet to an external Base address

Submit a withdrawal request. The requested amount is debited from your wallet immediately and held in a `pending` state until an admin approves or rejects the request.

A flat **\$0.50 fee** is deducted from the on-chain amount. If you request `$100`, your wallet is debited `$100` and `$99.50` USDC is sent to the destination address upon approval.

<ParamField header="Authorization" type="string" required>
  Bearer token. Example: `Bearer sk_staging_your_api_key`
</ParamField>

<ParamField header="idempotency-key" type="string" required>
  Unique key per request. Repeating the same key returns the existing withdrawal without creating a duplicate or double-debiting your wallet.
</ParamField>

<ParamField body="amount" type="number" required>
  USD amount to withdraw. Minimum: **\$5**. The on-chain transfer amount will be `amount - 0.50` (fee).
</ParamField>

<ParamField body="toAddress" type="string" required>
  Destination EVM address on Base (must match `^0x[a-fA-F0-9]{40}$`).
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://services-staging.getplu.com/api/v1/partner/withdrawal \
    -H "Authorization: Bearer sk_staging_your_api_key" \
    -H "Content-Type: application/json" \
    -H "idempotency-key: 9b1c0a30-7b6c-4f9c-8d6f-3a8e5e2a1f00" \
    -d '{
      "amount": 100,
      "toAddress": "0xa40aCe28a2d66f81D396c7F0ACd46Ae2e4407089"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://services-staging.getplu.com/api/v1/partner/withdrawal',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer sk_staging_your_api_key',
        'Content-Type': 'application/json',
        'idempotency-key': crypto.randomUUID(),
      },
      body: JSON.stringify({
        amount: 100,
        toAddress: '0xa40aCe28a2d66f81D396c7F0ACd46Ae2e4407089',
      }),
    }
  );
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "status": "success",
    "message": "Withdrawal request created",
    "data": {
      "id": "65f0d9f4c8a3b21e9d4a6c01",
      "partnerId": "service-partner-PdhFKbfvYr",
      "amount": 100,
      "fee": 0.5,
      "netAmount": 99.5,
      "toAddress": "0xa40aCe28a2d66f81D396c7F0ACd46Ae2e4407089",
      "chain": "base",
      "token": "usdc",
      "status": "pending",
      "createdAt": "2026-04-20T11:42:18.221Z"
    }
  }
  ```

  ```json 400 Below minimum theme={null}
  {
    "status": "error",
    "message": "AMOUNT_BELOW_MIN",
    "data": { "error": "Minimum withdrawal amount is $5" }
  }
  ```

  ```json 400 Insufficient balance theme={null}
  {
    "status": "error",
    "message": "INSUFFICIENT_BALANCE",
    "data": { "error": "Insufficient wallet balance" }
  }
  ```

  ```json 400 Invalid address theme={null}
  {
    "status": "error",
    "message": "VALIDATION_ERROR",
    "data": { "error": "toAddress must be a valid EVM address" }
  }
  ```
</ResponseExample>

<Info>
  Withdrawals require manual admin approval. The on-chain transfer happens only after approval — track status via [Get Withdrawal](/api-reference/withdrawals/get-withdrawal) or subscribe to the [`wallet.withdrawal.crypto`](/webhooks#wallet-events) webhook event.
</Info>

<Warning>
  USDC withdrawals are sent on the **Base** network. Do not provide an address from any other chain — funds sent to non-Base addresses cannot be recovered.
</Warning>

<Note>
  Deposits and withdrawals do not support the same networks. Your wallet is credited on any of the
  [supported networks](/webhooks#supported-networks) — including Polygon USDC, USDT and USDC.e, and Optimism
  USDC and USDT — but withdrawals are sent as **USDC on Base only**. There is no `chain` or `token` parameter
  on this endpoint; an Optimism USDT deposit is withdrawn as Base USDC.
</Note>
