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

# Withdraw from Yield

> Learn how to generate transaction bytecode for withdrawing from yield positions

In this section, you'll learn how to request ready-to-use transaction data (bytecode) for withdrawing from a yield position.

<Info>
  **Prerequisites:** - [How to Deposit](/guides/yield/deposit) - [How to Check
  Open Positions](/guides/yield/check-positions)
</Info>

## Protocol-Specific Approach

Use this when you want to work with a specific yield protocol.

**Request Transaction Data**

Fetch specific protocol information using:

```http theme={null}
GET /strategies/:id/bytecode
```

**Required Parameters:**

| Parameter | Description                     | Example                          |
| --------- | ------------------------------- | -------------------------------- |
| action    | Type of operation               | `withdraw` or `request-withdraw` |
| amount    | Amount in token's smallest unit | `10000000`                       |
| wallet    | Wallet that owns the position   | `0x1234...`                      |

**Optional Parameters (cross-chain):**

| Parameter               | Description                                                                                                                                                          | Example                                                     |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| toChainId or chainIdOut | Destination chain ID for the withdrawn funds                                                                                                                         | `8453` (Base)                                               |
| toTokenAddress          | Destination token address. **Required when `toChainId` or `chainIdOut` is provided.** If `toChainId`/`chainIdOut` is omitted, `toTokenAddress` is also not required. | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` (USDC on Base) |

**Optional Parameters (response format):**

| Parameter | Description                                                                                      | Example      |
| --------- | ------------------------------------------------------------------------------------------------ | ------------ |
| output    | Response format: `bytecode` (default), `userOperation`, `fireblocks`, or `instructions` (Solana) | `fireblocks` |
| accountId | Fireblocks vault account ID. **Required when `output=fireblocks`**                               | `12`         |

**Example Request:**

```http theme={null}
GET /strategies/aave-usdc-polygon/bytecode?action=withdraw&amount=10000000&wallet=0x1234...
```

**Example Request (cross-chain withdraw):**

```http theme={null}
GET /strategies/aave-usdc-arbitrum/bytecode?action=withdraw&amount=10000000&wallet=0x1234...&toChainId=8453&toTokenAddress=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```

**Example Response (same-chain withdraw):**

```json theme={null}
{
  "feeCharged": "0",
  "chainIdIn": 137,
  "chainIdOut": 137,
  "id": "65f3a1c8e9b2d4f8a7c1d2e3",
  "crossChain": {
    "isCrossChain": false,
    "chainIdIn": 137,
    "chainIdOut": 137
  },
  "quote": null,
  "bytecode": [
    {
      "to": "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
      "value": "0",
      "data": "0xe8eda9df...",
      "chainId": 137
    }
  ]
}
```

**Example Response (cross-chain withdraw):**

When `toChainId` differs from the strategy's chain, the response also includes a `quote` object describing the bridge selection, the resolved tokens, and the expected/minimum output amount. The `crossChain.isCrossChain` flag is `true`.

```json theme={null}
{
  "feeCharged": "0",
  "chainIdIn": 42161,
  "chainIdOut": 8453,
  "id": "6a04f2f75bf7233c6220b3ca",
  "crossChain": {
    "isCrossChain": true,
    "chainIdIn": 42161,
    "chainIdOut": 8453
  },
  "quote": {
    "bridge": "CCTP",
    "sender": "0x49A54d4d925868475Eb8d2cb2c784481ca755e8A",
    "fromChainId": 42161,
    "fromTokenAddress": "0x4F38e7a76b9C32Ab68FBf500E4d52806B15AB93b",
    "toChainId": 8453,
    "toTokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "inputAmount": {
      "value": "999870",
      "decimals": 18,
      "humanized": "0.00000000000099987",
      "symbol": "KPK-podsUSDCy"
    },
    "outputAmount": {
      "value": "999000",
      "decimals": 6,
      "humanized": "0.999",
      "symbol": "USDC"
    },
    "minimumOutputAmount": {
      "value": "999000",
      "decimals": 6,
      "humanized": "0.999",
      "symbol": "USDC"
    },
    "chainIdIn": 42161,
    "chainIdOut": 8453
  },
  "bytecode": [
    { "to": "0x...", "value": "0", "data": "0x...", "chainId": "42161" }
  ]
}
```

<Note>
  The top-level `id` is used for execution tracking — store it and pass it to `GET /actions/:id` to track the cross-chain withdrawal through completion (see [Checking Cross-Chain Withdrawal Status](#checking-cross-chain-withdrawal-status) below).

  The `quote` object describes which bridge was selected (`bridge`), the expected `outputAmount`, and the worst-case `minimumOutputAmount` (slippage floor). Display these to the user before they sign.
</Note>

**Example Request (Fireblocks output):**

If you are using Fireblocks custody, set `output=fireblocks` and pass your vault `accountId`. The `wallet` parameter must be a smart wallet previously provisioned via `POST /fireblocks-smart-account` (see [Fireblocks Integration](/external-integrations/fireblocks-integration)).

```http theme={null}
GET /strategies/aave-usdc-polygon/bytecode?action=withdraw&amount=10000000&wallet=0xSafeAddress&output=fireblocks&accountId=YOUR_VAULT_ACCOUNT_ID
```

**Example Response:**

```json theme={null}
{
  "feeCharged": "0",
  "chainIdIn": 137,
  "chainIdOut": 137,
  "id": "65f3a1c8e9b2d4f8a7c1d2e3",
  "crossChain": {
    "isCrossChain": false,
    "chainIdIn": 137,
    "chainIdOut": 137
  },
  "quote": null,
  "transactionData": {
    "transactionRequest": {
      "operation": "CONTRACT_CALL",
      "assetId": "MATIC_POLYGON",
      "source": {
        "type": "VAULT_ACCOUNT",
        "id": "YOUR_VAULT_ACCOUNT_ID"
      },
      "destination": {
        "type": "ONE_TIME_ADDRESS",
        "oneTimeAddress": {
          "address": "0xSafeAddress"
        }
      },
      "amount": "0",
      "extraParameters": {
        "contractCallData": "0x6a761202..."
      },
      "note": "withdraw aave-usdc-polygon",
      "failOnLowFee": true
    }
  }
}
```

The `transactionData.transactionRequest` payload can be submitted directly to the Fireblocks Transactions API (`POST /v1/transactions`) — no further encoding required. The Earn Owner vault must be configured as the signer (see [Fireblocks Integration](/external-integrations/fireblocks-integration#1-fireblocks-setup)). After the withdrawal completes, transfer funds out of the smart wallet to your Omnibus wallet or any other destination.

<Note>
  Use `GET /strategies` to list available protocols, then pass the chosen
  strategy ID into the protocol-specific approach above.
</Note>

## Executing the Transaction

<Warning>
  Batch all `bytecode` legs on the same `chainId` into **one atomic transaction**. See
  [Executing Bytecode](/getting-started/executing-bytecode).
</Warning>

```javascript theme={null}
const { data: result } = await pods.get('/strategies/aave-usdc-polygon/bytecode', {
  params: { action: 'withdraw', amount: '10000000', wallet: walletAddress }
})

// Batch result.bytecode into ONE tx — do not send each leg separately
console.log('Legs to batch atomically:', result.bytecode.length)
```

<Warning>
  Make sure you have sufficient balance in your position before attempting to
  withdraw. Check your open positions first using the [check positions
  endpoint](/guides/yield/check-positions).
</Warning>

## Checking Cross-Chain Withdrawal Status

Cross-chain withdrawals are asynchronous: the source-chain withdraw + bridge transaction is signed first, then the bridged funds are delivered on the destination chain. To track progress to completion, use the `id` returned in the bytecode response:

```http theme={null}
GET /actions/:id
```

**Path Parameters:**

| Parameter | Description                                         | Example                    |
| --------- | --------------------------------------------------- | -------------------------- |
| id        | The `id` returned by `GET /strategies/:id/bytecode` | `6a04f2f75bf7233c6220b3ca` |

**Example Request:**

```http theme={null}
GET /actions/6a04f2f75bf7233c6220b3ca
```

**Example Response (withdrawal in flight):**

```json theme={null}
{
  "id": "6a04f2f75bf7233c6220b3ca",
  "type": "CROSSCHAIN_INVESTMENT_WITHDRAW",
  "status": "PENDING",
  "strategyId": "65a1b2c3d4e5f6a7b8c9d0e1",
  "strategySlug": "aave-usdc-polygon",
  "initialDate": "2026-05-19T14:30:15Z",
  "createdAt": "2026-05-19T14:30:00Z",
  "originAddress": "0x49A54d4d925868475Eb8d2cb2c784481ca755e8A",
  "receiverAddress": "0x49A54d4d925868475Eb8d2cb2c784481ca755e8A",
  "amounts": {
    "assetIn": {
      "token": {
        "address": "0x4F38e7a76b9C32Ab68FBf500E4d52806B15AB93b",
        "symbol": "KPK-podsUSDCy",
        "decimals": 18
      },
      "chain": { "id": 42161, "name": "arbitrum" },
      "amountRaw": "999870",
      "amountHumanized": "0.00000000000099987",
      "amountInUSD": "1.00"
    },
    "assetOut": {
      "token": {
        "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "symbol": "USDC",
        "decimals": 6
      },
      "chain": { "id": 8453, "name": "base" },
      "amountRaw": "999000",
      "amountHumanized": "0.999",
      "amountInUSD": "1.00"
    }
  },
  "transactions": [
    {
      "chain": "arbitrum",
      "txHash": "0xabc...",
      "blockNumber": 19234567,
      "timestamp": "2026-05-19T14:30:15Z",
      "status": "SUCCESS",
      "underlyingAssetFeeValue": "0"
    },
    {
      "chain": "base",
      "txHash": null,
      "blockNumber": null,
      "timestamp": null,
      "status": "PENDING",
      "underlyingAssetFeeValue": null
    }
  ],
  "finishedAt": null,
  "underlyingAssetFeeValue": "0"
}
```

**Status values:**

| Status            | Meaning                                                      |
| ----------------- | ------------------------------------------------------------ |
| `INITIAL`         | Created, awaiting on-chain execution                         |
| `PENDING`         | At least one transaction broadcast; awaiting confirmations   |
| `SUCCESS`         | All steps completed; funds arrived on the destination chain  |
| `FAILED`          | A step failed                                                |
| `REFUND_REQUIRED` | Funds withdrawn but the bridge step failed; refund is needed |
| `REFUNDED`        | Refund completed                                             |
| `EXPIRED`         | Quote expired before execution                               |

Poll this endpoint until `status` reaches a terminal value (`SUCCESS`, `FAILED`, `REFUNDED`, or `EXPIRED`). The `transactions` array lists each on-chain hash as it is confirmed.

<Note>
  Same-chain withdrawals do not need this polling — the withdraw completes
  inline with the user's signed transaction. The `id` is still returned for
  record-keeping and can be queried the same way.
</Note>

## Webhook Notifications

As an alternative to polling, Pods can push every status transition to a URL you control. The payload is identical to `GET /actions/:id`, so you can drive the same UI off either source.

<Info>
  Webhook URL configuration is currently provisioned manually — contact the Pods team to register your `webhookURL` (and any optional custom headers, e.g. an HMAC signature header). Self-service configuration via the admin panel is coming soon.
</Info>

**Transport:**

| Field          | Value                                                             |
| -------------- | ----------------------------------------------------------------- |
| Method         | `POST`                                                            |
| URL            | Your `webhookURL`                                                 |
| `Content-Type` | `application/json`                                                |
| Custom headers | Any headers you configure with the team are sent on every request |

**Body shape:**

```json theme={null}
{
  "messageType": "ACTION_UPDATE",
  "data": {
    /* same object returned by GET /actions/:id */
  }
}
```

**Example payload (cross-chain withdrawal reaching `SUCCESS`):**

```json theme={null}
{
  "messageType": "ACTION_UPDATE",
  "data": {
    "id": "6a04f2f75bf7233c6220b3ca",
    "type": "CROSSCHAIN_INVESTMENT_WITHDRAW",
    "status": "SUCCESS",
    "strategyId": "65a1b2c3d4e5f6a7b8c9d0e1",
    "strategySlug": "aave-usdc-polygon",
    "initialDate": "2026-05-19T14:30:15Z",
    "createdAt": "2026-05-19T14:30:00Z",
    "originAddress": "0x49A54d4d925868475Eb8d2cb2c784481ca755e8A",
    "receiverAddress": "0x49A54d4d925868475Eb8d2cb2c784481ca755e8A",
    "amounts": {
      "assetIn": {
        "token": {
          "address": "0x4F38e7a76b9C32Ab68FBf500E4d52806B15AB93b",
          "symbol": "KPK-podsUSDCy",
          "decimals": 18
        },
        "chain": { "id": 42161, "name": "arbitrum" },
        "amountRaw": "999870",
        "amountHumanized": "0.00000000000099987",
        "amountInUSD": "1.00"
      },
      "assetOut": {
        "token": {
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "symbol": "USDC",
          "decimals": 6
        },
        "chain": { "id": 8453, "name": "base" },
        "amountRaw": "999000",
        "amountHumanized": "0.999",
        "amountInUSD": "1.00"
      }
    },
    "transactions": [
      {
        "chain": "arbitrum",
        "txHash": "0xabc...",
        "blockNumber": 248123456,
        "timestamp": "2026-05-19T14:30:15Z",
        "status": "SUCCESS"
      },
      {
        "chain": "base",
        "txHash": "0xdef...",
        "blockNumber": 19234999,
        "timestamp": "2026-05-19T14:33:02Z",
        "status": "SUCCESS"
      }
    ],
    "finishedAt": "2026-05-19T14:33:02Z"
  }
}
```

**Delivery semantics:**

* A request fires for **every** status change, so you may receive multiple deliveries per withdrawal (`INITIAL` → `PENDING` → `SUCCESS`).
* Pods expects a `2xx` response. Non-`2xx` responses are recorded but not automatically retried; reconcile with `GET /actions/:id` if you need at-least-once guarantees.
* Respond as quickly as possible; do the heavy work asynchronously on your side.

## Next Steps

<CardGroup cols={2}>
  <Card title="Check Positions" icon="chart-line" href="/guides/yield/check-positions">
    View your remaining positions
  </Card>

  <Card title="New Deposit" icon="arrow-up-right-dots" href="/guides/yield/deposit">
    Make a new deposit
  </Card>

  <Card title="Protocol Info" icon="circle-info" href="/guides/yield/check-protocol-info">
    Check protocol information
  </Card>
</CardGroup>
