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

# Withdrawal

> Withdraw a node operator's restaked Ethereum with the P2P.org Restaking API.

For the Restaking API, it is possible to withdraw the node operator's staked Ethereum in one of two ways:

1. Partial withdrawal of the rewards balance staked above 32 ETH.
2. Full withdrawal of all staked assets, followed by liquidating the operator node and exiting the network.

Both flows include a checkpoint proof, which allows checking and comparing the EigenPod and Beacon chain balances. After completing a checkpoint, it is possible to either withdraw accumulated yield or continue with withdrawing the whole stake fully.

<Warning>
  Note that only one active checkpoint can be run per an EigenPod, and once started, checkpoints cannot be cancelled (only completed). Since the <Tooltip tip="A measure of computational effort required to execute a transaction or smart contract on a blockchain. Users must pay a gas fee, usually in the native token, to have their transactions processed by the network.">gas</Tooltip> cost of a checkpoint does not depend on the reward amount, it is essential to plan these checkpoints accordingly. In general, starting a new checkpoint more frequently than in 8 days would result in no benefit for the user.
</Warning>

Request examples are provided using [cURL](https://curl.se/).

***

To initiate a withdrawal in the Ethereum network using the Restaking API, follow these steps:

1. Start Checkpoint: construct a serialized transaction to start a checkpoint, proving the expected funds are deposited in the EigenPod and/or validator.
2. Verify Checkpoint Proofs: construct a serialized transaction to verify received proofs.

At this stage, the partial withdrawal scenario is complete.

To fully withdraw a validator and its earnings, continue with the additional steps:

3. Prepare Undelegate Restake Transaction: construct a serialized transaction to undelegate the staked amount of tokens from a node operator.
4. Queue Withdrawals: construct a serialized transaction to queue withdrawals.
5. Create Withdrawal Request: construct a serialized transaction to initiate the validator's exit from the network.
6. Complete Queued Withdrawals: construct a serialized transaction to complete queued withdrawals after the escrow period.

## 1. Start Checkpoint Proof

1\. Create a serialized transaction to start a checkpoint by sending a POST request to [/api/v1/eth/staking/eigenlayer/tx/start-checkpoint](/reference/eth-eigen-start-checkpoint).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/start-checkpoint \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <token>' \
       --data '
  {
    "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/start-checkpoint", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/start-checkpoint",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/start-checkpoint", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `eigenPodOwnerAddress` — owner of the EigenPod address.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
        "to": "0xaE1ACF4F8bf25D9Aa365E2986BaB1d1B201Bb59c",
        "gasLimit": "10000000",
        "data": "0x88676cad00000000000000000000000000000000000000000",
        "value": "0",
        "chainId": "17000",
        "type": "2",
        "maxFeePerGas": "1000038",
        "maxPriorityFeePerGas": "1000000"
      },
      "error": {}
    }
  ```
</CodeGroup>

* `serializeTx` — serialized <Tooltip tip="A transaction that must be signed and broadcasted to the blockchain network.">unsigned transaction</Tooltip>.
* `to` — recipient address for this transaction.
* `gasLimit` — maximum gas limit for this block.
* `data` — transaction data.
* `value` — amount this transaction is sending in Wei.
* `chainId` — chain ID this transaction is authorized on, as specified by [EIP-155](https://eips.ethereum.org/EIPS/eip-155).
* `type` — [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) type of this transaction envelope.
* `maxFeePerGas` — maximum price per unit of gas this transaction will pay for the combined [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) block's base fee and this transaction's priority fee in Wei.
* `maxPriorityFeePerGas` — price per unit of gas in Wei, which is added to the [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) block's base fee. This added fee is used to incentivize miners to prioritize this transaction.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network.

By broadcasting this transaction, you are beginning the process of proving that the amount of validator ETH is active and its withdrawal credentials are pointing to the EigenPod.

## 2. Verify Checkpoint Proofs

1\. Create a serialized transaction to verify received checkpoint proofs by sending a POST request to [/api/v1/eth/staking/eigenlayer/tx/verify-checkpoint-proofs](/reference/eth-eigen-verify-checkpoint-proofs).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/verify-checkpoint-proofs \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <token>' \
       --data '
  {
    "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
    "activateTx": "0x968be713c254134163da7aefef4f27b02b96a393d56306ea471d"
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/verify-checkpoint-proofs", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
      "activateTx": "0x968be713c254134163da7aefef4f27b02b96a393d56306ea471d"
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/verify-checkpoint-proofs",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
          "activateTx": "0x968be713c254134163da7aefef4f27b02b96a393d56306ea471d"
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
  		"activateTx": "0x968be713c254134163da7aefef4f27b02b96a393d56306ea471d",
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/verify-checkpoint-proofs", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `eigenPodOwnerAddress` — owner of the EigenPod address.
* `activateTx` — hash of the start checkpoint transaction.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
        "to": "0xaE1ACF4F8bf25D9Aa365E2986BaB1d1B201Bb59c",
        "gasLimit": "10000000",
        "data": "0x88676cad00000000000000000000000000000000000000000",
        "value": "0",
        "chainId": "17000",
        "type": "2",
        "maxFeePerGas": "1000038",
        "maxPriorityFeePerGas": "1000000"
      },
      "error": {}
    }
  ```
</CodeGroup>

Example response is the same as in the [Start Checkpoint Proof](/docs/restaking-eth#1-start-checkpoint-proof) step.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network.

<Warning>
  **Note that the transaction signing is time sensitive**

  The transaction has to be signed in 8192 slots (approximately 27 hours).

  If the time has expired and you have not signed the transaction yet, [contact](/docs/contacts) us for support.
</Warning>

By broadcasting this transaction, you are making progress on submitting checkpoint proofs to EigenLayer contracts. After the checkpoint completion, the rewards will be withdrawn to the `eigenPodOwnerAddress`.

This is the last step in the partial withdrawal flow.

## 3. Create Undelegate Request

To continue the flow to fully withdraw the stake and the rewards amount:

1\. Construct a serialized transaction to undelegate the staked amount of tokens from a node operator by sending a POST request to [/api/v1/eth/staking/eigenlayer/tx/undelegate](/reference/eth-eigen-undelegate).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/undelegate \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <token>' \
       --data '
  {
    "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/undelegate", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/undelegate",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5"
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/undelegate", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `eigenPodOwnerAddress` — owner of the EigenPod address.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
        "to": "0xA44151489861Fe9e3055d95adC98FbD462B948e7",
        "gasLimit": "10000000",
        "data": "0xda8be864000000000000000000000000368f823e4dfe271dc82",
        "value": "0",
        "chainId": "17000",
        "type": "2",
        "maxFeePerGas": "1000036",
        "maxPriorityFeePerGas": "1000000"
      },
      "error": {}
    }
  ```
</CodeGroup>

Example response is the same as in the [Start Checkpoint Proof](/docs/restaking-eth#1-start-checkpoint-proof) step.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network.

## 4. Queue Withdrawals

1\. Construct a serialized transaction to queue withdrawals for all the deposited tokens by sending a POST request to [/api/v1/eth/staking/eigenlayer/tx/queue-withdrawals](/reference/eth-eigen-queue-withdrawals).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/queue-withdrawals \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <token>' \
       --data '
  {
    "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
    "amount": "32"
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/queue-withdrawals", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
      "amount": "32"
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/queue-withdrawals",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
          "amount": "32"
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
  		"amount": "32",
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/queue-withdrawals", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `eigenPodOwnerAddress` — owner of the EigenPod address.
* `amount` — amount of ETH that is being unstaked.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
        "to": "0xA44151489861Fe9e3055d95adC98FbD462B948e7",
        "gasLimit": "10000000",
        "data": "0x0dd8dd0200000000000000000000000000000000000000000",
        "value": "0",
        "chainId": "17000",
        "type": "2",
        "maxFeePerGas": "1000034",
        "maxPriorityFeePerGas": "1000000"
      },
      "error": {}
    }
  ```
</CodeGroup>

Example response is the same as in the [Start Checkpoint Proof](/docs/restaking-eth#1-start-checkpoint-proof) step.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network.

## 5. Prepare Withdrawal Transaction

1\. Construct a serialized transaction to initiate the network exit for active validators by sending a POST request to [/api/v1/eth/staking/direct/tx/withdrawal](/reference/eth-staking-withdrawal).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/direct/tx/withdrawal \
       --header 'accept: application/json' \
       --header 'authorization: Bearer <token>' \
       --header 'content-type: application/json' \
       --data '
  {
    "pubkeys": [
      "0xffC08FcD7cFeF5c70fB2b0e1f2A8EaA690AaE2bDFfa5dBEc4dEef31DcC0B19eB1f9Cebe3E2fe9eefBD9a1BDF6FD89b39"
    ]
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/direct/tx/withdrawal", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "pubkeys": [
        "0xffC08FcD7cFeF5c70fB2b0e1f2A8EaA690AaE2bDFfa5dBEc4dEef31DcC0B19eB1f9Cebe3E2fe9eefBD9a1BDF6FD89b39"
      ]
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/direct/tx/withdrawal",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "pubkeys": [
              "0xffC08FcD7cFeF5c70fB2b0e1f2A8EaA690AaE2bDFfa5dBEc4dEef31DcC0B19eB1f9Cebe3E2fe9eefBD9a1BDF6FD89b39"
          ]
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"pubkeys": []interface{}{"0xffC08FcD7cFeF5c70fB2b0e1f2A8EaA690AaE2bDFfa5dBEc4dEef31DcC0B19eB1f9Cebe3E2fe9eefBD9a1BDF6FD89b39"},
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/direct/tx/withdrawal", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `pubkeys` — list of validators public keys.

Example response:

<CodeGroup>
  ```json theme={null}
  {
       "result": {
          "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
          "to": "0x8C87EFBA90414687A66C8B2E7D21039E81d55456",
          "gasLimit": "100000",
          "data": "0x0dd8dd0200000000000000000000000000000000000000000",
          "value": "0",
          "chainId":17000,
          "type": 2,
          "maxFeePerGas": "1000036",
          "maxPriorityFeePerGas" : "1000000"
       }      
    }
  ```
</CodeGroup>

Example response is the same as in the [Start Checkpoint Proof](/docs/restaking-eth#1-start-checkpoint-proof) step.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network. By broadcasting this transaction, you are submitting the validator's exit from the Ethereum network.

<Warning>
  **There is a withdrawal delay for EigenLayer contracts**

  As a security measure, users have to wait for an escrow period before they can withdraw unstaked assets.

  For testing environment, it takes 10 blocks, which is roughly 2 minutes, and for the mainnet, it takes up to 7 days.
</Warning>

## 6. Complete Queued Withdrawals

1\. After the withdrawal escrow period has elapsed, construct a serialized transaction to complete queued withdrawals by sending a POST request to [/api/v1/eth/staking/eigenlayer/tx/complete-queued-withdrawals](/reference/eth-eigen-complete-queued-withdrawals).

Example request:

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/complete-queued-withdrawals \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <token>' \
       --data '
  {
    "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
    "queueWithdrawalsTx": "0x5d7baf40071d011f784ced45fa815ea25dfd659837db"
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/complete-queued-withdrawals", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
      "queueWithdrawalsTx": "0x5d7baf40071d011f784ced45fa815ea25dfd659837db"
    }),
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/complete-queued-withdrawals",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json",
      },
      json={
          "eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
          "queueWithdrawalsTx": "0x5d7baf40071d011f784ced45fa815ea25dfd659837db"
      },
  )
  print(response.json())
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := map[string]interface{}{
  		"eigenPodOwnerAddress": "0x27AABeE07E0dbC8b0de20f42b1a1980871314Ef5",
  		"queueWithdrawalsTx": "0x5d7baf40071d011f784ced45fa815ea25dfd659837db",
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/eth/staking/eigenlayer/tx/complete-queued-withdrawals", bytes.NewBuffer(body))
  	req.Header.Set("Authorization", "Bearer <token>")
  	req.Header.Set("Content-Type", "application/json")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  	respBody, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(respBody))
  }
  ```
</CodeGroup>

* `eigenPodOwnerAddress` — owner of the EigenPod address.
* `queueWithdrawalsTx` — hash of the queue withdrawals transaction.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "serializeTx": "0x02f902d705808301674e8508530af16e830186a094681a1b3441c6bfb12f91651efd9f02c83c0702938901bc16d674ec800000b902a44f498c730000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030aa5f27070a21d79455c4a9b73c0aa4a8b1a65a1fb530d7fd8e6cd23aa16660679ac43ee4861098f6d9166aed3a4d8abb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000028c84612d37de9209018ad96167f12169b653e9a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060978c565cd915f4e885b4201093d1501697610eb9ee99b9b60b70434dc330e98d5b42927725304ded48483a8b8f39506d09bcb22ee18d4f6b50257946ac5ee360385308d95c0e2bc963902d42e985c29ee489aa3c989ac1561c952a6424f107a800000000000000000000000000000000000000000000000000000000000000014cb452f6e3f10ba2175c86a0284f53fcb61404b458393391abc3d5622e3e55cdc0",
        "to": "0xA44151489861Fe9e3055d95adC98FbD462B948e7",
        "gasLimit": "10000000",
        "data": "0x3340439600000000000000000000000000000000000000000",
        "value": "0",
        "chainId": "17000",
        "type": "2",
        "maxFeePerGas": "1000028",
        "maxPriorityFeePerGas": "1000000"
      },
      "error": {}
    }
  ```
</CodeGroup>

Example response is the same as in the [Start Checkpoint Proof](/docs/restaking-eth#1-start-checkpoint-proof) step.

2\. Use `serializeTx` to [sign and send](/docs/signing-transaction-eth) the signed transaction to the Ethereum network.


## Related topics

- [Getting Started](/docs/restaking-eth.md)
- [Restaking API reference](/reference/eth-eigen-create-pod.md)
