> ## 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.

# Getting Started

> Stake on Polkadot programmatically with the P2P.org Staking API.

There are two ways to start staking on the Polkadot network using the Staking API with a public node:

* Stake directly.
* Stake via a <Tooltip tip="On Polkadot and Avail, nomination pools allow users to contribute tokens and earn staking rewards. Unlike nominating directly, where your bonded funds remain in your account but become locked, the tokens you bond to a pool is transferred to the pool's stash account. Staking using pools requires a small amount of tokens, and the pool manages nominees on your behalf.">nomination pool</Tooltip>.

[Get an authentication token](/docs/authentication) to start using Staking API. For staking, it is essential to keep a minimum deposit of 1 DOT on the account.

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

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant P2P API
    participant Blockchain
    rect rgb(240, 248, 255)
    note right of Client: Direct Staking
    Client->>P2P API: Create bond transaction
    P2P API-->>Client: Unsigned bond transaction
    Client->>Client: Sign transaction locally
    Client->>Blockchain: Broadcast bond transaction
    Blockchain-->>Client: Bond confirmed
    Client->>P2P API: Create nomination transaction
    P2P API-->>Client: Unsigned nomination transaction
    Client->>Client: Sign transaction locally
    Client->>Blockchain: Broadcast nomination transaction
    Blockchain-->>Client: Nomination confirmed
    end
    rect rgb(255, 248, 240)
    note right of Client: Nomination Pool
    Client->>P2P API: Create pool bond transaction
    P2P API-->>Client: Unsigned pool bond transaction
    Client->>Client: Sign transaction locally
    Client->>Blockchain: Broadcast pool bond transaction
    Blockchain-->>Client: Pool bond confirmed
    end
```

## Staking directly

### 1. Create bonding request

1. Send a POST request to [/api/v1/polkadot/\{network}/staking/bond](/reference/polkadot-staking-bond). Note that there is a [dynamic minimum threshold to stake](https://wiki.polkadot.network/docs/learn-staking).

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/polkadot/westend/staking/bond \
       --header 'accept: application/json' \
       --header 'authorization: Bearer <token>' \
       --header 'content-type: application/json' \
       --data '
  {
    "stashAccountAddress": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
    "rewardDestinationType": "account",
    "rewardDestination": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
    "amount": 1,
    "extended": true
  }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/staking/bond",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        rewardDestinationType: "account",
        rewardDestination: "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        amount: 1,
        extended: true,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/staking/bond",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
          "rewardDestinationType": "account",
          "rewardDestination": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
          "amount": 1,
          "extended": True,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress":   "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
  		"rewardDestinationType": "account",
  		"rewardDestination":     "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
  		"amount":                1,
  		"extended":              true,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/staking/bond", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main <Tooltip tip="On Polkadot and Avail, this is an account that holds funds bonded for staking, but delegates all staking functions to a staking proxy account. You may actively participate in staking with a stash private key kept in a cold wallet like Ledger, meaning it stays offline all the time. Having a staking proxy will allow you to sign all staking-related transactions with the proxy instead of using your Ledger device. This will allow you to avoid carrying around your Ledger device just to sign staking-related transactions, and to keep the transaction history of your stash clean.">stash account</Tooltip> address which keeps tokens for <Tooltip tip="On Polkadot and Avail, a process by which tokens can be “frozen” in exchange for rewards. For example, staking is a form of bonding for which you receive rewards in exchange for securing the network.">bonding</Tooltip>.

* `rewardDestinationType` — rewards destination type:

  * `staked` — rewards will be sent to the <Tooltip tip="On Polkadot and Avail, this is an account that holds funds bonded for staking, but delegates all staking functions to a staking proxy account. You may actively participate in staking with a stash private key kept in a cold wallet like Ledger, meaning it stays offline all the time. Having a staking proxy will allow you to sign all staking-related transactions with the proxy instead of using your Ledger device. This will allow you to avoid carrying around your Ledger device just to sign staking-related transactions, and to keep the transaction history of your stash clean.">stash account</Tooltip> and added to the current bond (compounding rewards).
  * `stash` — rewards will be sent to the <Tooltip tip="On Polkadot and Avail, this is an account that holds funds bonded for staking, but delegates all staking functions to a staking proxy account. You may actively participate in staking with a stash private key kept in a cold wallet like Ledger, meaning it stays offline all the time. Having a staking proxy will allow you to sign all staking-related transactions with the proxy instead of using your Ledger device. This will allow you to avoid carrying around your Ledger device just to sign staking-related transactions, and to keep the transaction history of your stash clean.">stash account</Tooltip> as a transferable balance (not compounding rewards).
  * `account` — rewards will be sent to any account specified as a transferable balance.

* `rewardDestination` — rewards destination account address.

* `amount` — amount of tokens to bond. DOT is used for the main network, KSM for Kusama, and WND for Westend.

* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata in the response. This information may be crucial for integrating with custodial platforms, offline signers, or advanced transaction builders.

Example response (for `extended` parameter set to `true`):

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0xa8040600070010a5d4e803f690e412f0f0d6a963b89e78f9f44015c8909b2ee57836fff9a739e56897d51b",
        "unsignedTransactionSerialized": "7b2261646472657373223a223548647a67....",
        "unsignedTransactionPayload": "0x0600070010a5d4e803f690e412f0f0d6a963b89e78f9f44015c8909b2ee57836fff9a739e56897d51b",
        "unsignedTransactionObject": {
          "blockHash": "0xe9ee44203904ee47859882a6944bb9cb57a28a21146d699f0f731076f3beffe2",
          "eraPeriod": 64,
          "genesisHash": "0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
          "metadataRpc": "0x6d6574610e150f000c1c73705f636f72...",
          "method": {
            "args": {
              "value": "1,000,000,000,000",
              "payee": {
                "Account": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE"
              }
            },
            "method": "bond",
            "section": "staking"
          },
          "nonce": 1,
          "specVersion": 1018001,
          "transactionVersion": 27,
          "tip": 0
        },
        "stashAccountAddress": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        "rewardDestinationType": "account",
        "rewardDestination": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        "amount": 1,
        "createdAt": "2025-04-02T15:38:35.826Z"
      }
    }
  ```
</CodeGroup>

* `unsignedTransaction` — <Tooltip tip="A transaction that must be signed and broadcasted to the blockchain network.">unsigned transaction</Tooltip> in the hexadecimal format. Sign the transaction and submit it to the blockchain to perform the called action.

* `unsignedTransactionSerialized` — unsigned serialized transaction.

* `unsignedTransactionObject` — full decoded transaction structure with all metadata:

  * `blockHash`— hash of the checkpoint block in which the transaction was included.
  * `eraPeriod` — validity period of the transaction, representing the number of blocks after the checkpoint for which the transaction is valid.
  * `currentEra` — current staking era of the transaction.
  * `genesisHash` — hash of the genesis block.
  * `metadataRpc` — serialized metadata used for offline decoding and transaction signing.
  * `method` is the list of data fields containing information on the method called to construct a transaction.
  * `nonce` — nonce of the transaction.
  * `specVersion` — current version of the chain specification for the runtime.
  * `transactionVersion` — current version of the transaction format.
  * `tip` — optional fee used to increase the transaction priority.

* `stashAccountAddress` — main stash account address which keeps tokens for <Tooltip tip="On Polkadot and Avail, a process by which tokens can be “frozen” in exchange for rewards. For example, staking is a form of bonding for which you receive rewards in exchange for securing the network.">bonding</Tooltip>.

* `rewardDestinationType` — rewards destination type:

  * `staked` — rewards will be sent to the stash account and added to the current bond (compounding rewards).
  * `stash` — rewards will be sent to the stash account as a transferable balance (not compounding rewards).
  * `account` — rewards will be sent to any account specified as a transferable balance.

* `rewardDestination` — rewards destination account address.

* `amount` — amount of tokens to bond. DOT is used for the main network, KSM for Kusama, and WND for Westend.

* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.

### 2. Create nomination request

<Warning>
  **Accessing high-APR nodes**

  To benefit from P2P.org's high-APR <Tooltip tip="A network participant responsible for proposing new blocks under a Proof-of-Stake consensus model, validating transactions, and securing a blockchain through staking tokens. Validators play a crucial role in maintaining the security and integrity of the network.">validator</Tooltip>s on Polkadot (DOT), you must attach the **P2P.org proxy** to your account. These private <Tooltip tip="A network participant responsible for proposing new blocks under a Proof-of-Stake consensus model, validating transactions, and securing a blockchain through staking tokens. Validators play a crucial role in maintaining the security and integrity of the network.">validator</Tooltip>s require explicit approval and cannot be nominated via standard methods. Ensure the proxy is attached during your integration flow to unlock the enhanced staking rewards.

  Contact our [team](/docs/contacts) for dedicated assistance.
</Warning>

1. Send a POST request to [/api/v1/polkadot/\{network}/staking/nominate](/reference/polkadot-staking-nominate) to select validators within the Polkadot network.

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/polkadot/westend/staking/nominate \
       --header 'accept: application/json' \
       --header 'authorization: Bearer <token>' \
       --header 'content-type: application/json' \
       --data '
  {
    "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
    "extended": false
  }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/staking/nominate",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        extended: false,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/staking/nominate",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
          "extended": False,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  		"extended":            false,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/staking/nominate", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main stash account address which keeps tokens for <Tooltip tip="On Polkadot and Avail, a process by which tokens can be “frozen” in exchange for rewards. For example, staking is a form of bonding for which you receive rewards in exchange for securing the network.">bonding</Tooltip>.
* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata in the response.

Example response (for `extended` request parameter set to `false`):

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0x2102040605100096b33e0a9647f13198ad16a2812c549a363646a3a7ddbdcc5590f5839c408c6200767f36484b1e2acf5c265c7a64bfb46e95259c66a8189bbcd216195def43685200c21ad1e5198cc0dc3b0f9f43a50f292678f63235ea321e59385d7ee45a7208360018164fa6f9ce28792fb781185e8de4e6eaae34c0f545e5864952fe23c183df0c",
        "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        "targets": [
          "5FUJHYEzKpVJfNbtXmR9HFqmcSEz6ak7ZUhBECz7GpsFkSYR",
          "5Ek5JCnrRsyUGYNRaEvkufG1i1EUxEE9cytuWBBjA9oNZVsf",
          "5GTD7ZeD823BjpmZBCSzBQp7cvHR1Gunq7oDkurZr9zUev2n",
          "5CcHdjf6sPcEkTmXFzF2CfH7MFrVHyY5PZtSm1eZsxgsj1KC"
        ],
        "createdAt": "2023-09-18T14:49:23.998Z"
      }
    }
  ```
</CodeGroup>

* `unsignedTransaction` — <Tooltip tip="A transaction that must be signed and broadcasted to the blockchain network.">unsigned transaction</Tooltip> in hex format. Sign the transaction and submit it to the blockchain to perform the called action.
* `stashAccountAddress` — main stash account address which keeps tokens for bonding.
* `targets` — addresses of validators selected in the targets.
* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.

### 3. Add proxy account — optional step

It is possible to add a <Tooltip tip="On Polkadot and Avail, this is an account that acts on behalf of the stash account, signalling decisions about nominating and validating. It can set preferences like commission (for validators) and the staking rewards payout account. The earned rewards can be locked immediately for bonding on your stash account, which would effectively compound the rewards you receive over time. You could also choose to have them deposited to a different account as a free (transferable) balance. If you are a validator, it can also be used to set your session keys. Staking proxies only need sufficient funds to pay for the transaction fees.">staking proxy</Tooltip> to utilize the main stash account less frequently. It allows delegating your staking rights to another account, which can then sign transactions on your behalf. The original account retains all of its rights, and the proxy account can be removed at any time.

1. Send a POST request to [/api/v1/polkadot/\{network}/account/add](/reference/polkadot-account-add).

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/polkadot/westend/account/add \
       --header 'accept: application/json' \
       --header 'authorization: Bearer <token>' \
       --header 'content-type: application/json' \
       --data '
  {
    "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
    "proxyAccountAddress": "5Ggpg3JepXM3ZrktNpoc5QA1sKaFVpUPWMRr7jppiMxTuU75",
    "extended": false
  }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/account/add",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        proxyAccountAddress: "5Ggpg3JepXM3ZrktNpoc5QA1sKaFVpUPWMRr7jppiMxTuU75",
        extended: false,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/account/add",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
          "proxyAccountAddress": "5Ggpg3JepXM3ZrktNpoc5QA1sKaFVpUPWMRr7jppiMxTuU75",
          "extended": False,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  		"proxyAccountAddress": "5Ggpg3JepXM3ZrktNpoc5QA1sKaFVpUPWMRr7jppiMxTuU75",
  		"extended":            false,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/account/add", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main stash account address which keeps tokens for bonding; a proxied address that transfers rights to a proxy account.
* `proxyAccountAddress` — address that receives rights from the proxied account.
* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata.

Example response (for `extended` request parameter set to `false`):

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0xa404160100cc7cb7325ad1208212e2d8ee41a7572e816d53ac1bcac1be5df433486819213c0200000000",
        "createdAt": "2023-09-18T14:49:23.998Z"
      }
    }
  ```
</CodeGroup>

* `unsignedTransaction` — <Tooltip tip="A transaction that must be signed and broadcasted to the blockchain network.">unsigned transaction</Tooltip> in hex format. Sign the transaction and submit it to the blockchain to perform the called action.
* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.

## Staking via a nomination pool

### 1. Create bonding request

1. Create a bond request by sending a POST request to [/api/v1/polkadot/\{network}/staking/pool/bond](/reference/polkadot-pool-bond). The P2P.org pool ID on Polkadot mainnet is **238**.

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url https://api.p2p.org/api/v1/polkadot/westend/staking/pool/bond \
    --header 'accept: application/json' \
    --header 'authorization: Bearer <token>' \
    --header 'content-type: application/json' \
    --data '
  {
  "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  "poolId": 238,
  "amount": 3,
  "extended": true
  }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/bond",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        poolId: 238,
        amount: 3,
        extended: true,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/bond",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
          "poolId": 238,
          "amount": 3,
          "extended": True,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  		"poolId":              238,
  		"amount":              3,
  		"extended":            true,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/bond", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main stash account address which keeps tokens for bonding.

* `poolId` — ID of the nomination pool.

* `amount` — amount of tokens to bond. DOT is used for the main network, KSM for Kusama, and WND for Westend.

* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata in the response. This information may be crucial for integrating with custodial platforms, offline signers, or advanced transaction builders.

Example response (for `extended` parameter set to `true`):

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0xac0406000b00487835a302032c6eca5cdaa3e87d7f8e06d10015bf0508b52d301c8991af113d5cf49a53553f",
        "unsignedTransactionSerialized": "7b2261646472657373223a223548647a67....",
        "unsignedTransactionPayload": "0x0600070010a5d4e803f690e412f0f0d6a963b89e78f9f44015c8909b2ee57836fff9a739e56897d51b",
        "unsignedTransactionObject": {
          "blockHash": "0xe9ee44203904ee47859882a6944bb9cb57a28a21146d699f0f731076f3beffe2",
          "eraPeriod": 64,
          "genesisHash": "0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
          "metadataRpc": "0x6d6574610e150f000c1c73705f636f72...",
          "method": {
            "args": {
              "value": "3,000,000,000,000",
              "payee": {
                "Account": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE"
              }
            },
            "method": "bond",
            "section": "staking"
          },
          "nonce": 1,
          "specVersion": 1018001,
          "transactionVersion": 27,
          "tip": 0
        },
        "stashAccountAddress": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        "rewardDestinationType": "account",
        "rewardDestination": "5HdzgJMcKFwCeiso1izCWGLyVLk9YFztVFjK4rCadNXz6ztE",
        "amount": 3,
        "createdAt": "2025-04-02T15:38:35.826Z"
      }
    }
  ```
</CodeGroup>

* `unsignedTransaction` — unsigned transaction in the hexadecimal format. Sign the transaction and submit it to the blockchain to perform the called action.

* `unsignedTransactionSerialized` — unsigned serialized transaction.

* `unsignedTransactionObject` — full decoded transaction structure with all metadata:

  * `blockHash`— hash of the checkpoint block in which the transaction was included.
  * `eraPeriod` — validity period of the transaction, representing the number of blocks after the checkpoint for which the transaction is valid.
  * `currentEra` — current staking era of the transaction.
  * `genesisHash` — hash of the genesis block.
  * `metadataRpc` — serialized metadata used for offline decoding and transaction signing.
  * `method` is the list of data fields containing information on the method called to construct a transaction.
  * `nonce` — nonce of the transaction.
  * `specVersion` — current version of the chain specification for the runtime.
  * `transactionVersion` — current version of the transaction format.
  * `tip` — optional fee used to increase the transaction priority.

* `stashAccountAddress` — main stash account address which keeps tokens for bonding.

* `rewardDestinationType` — rewards destination type:

  * `staked` — rewards will be sent to the stash account and added to the current bond (compounding rewards).
  * `stash` — rewards will be sent to the stash account as a transferable balance (not compounding rewards).
  * `account` — rewards will be sent to any account specified as a transferable balance.

* `rewardDestination` — rewards destination account address.

* `amount` — amount of tokens to bond. DOT is used for the main network, KSM for Kusama, and WND for Westend.

* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.

### 2. Create setting permission request

1. Grant permission to the pool for managing rewards on your behalf by sending a POST request to [api/v1/polkadot/\{network}/staking/pool/set-claim-permission](/reference/polkadot-pool-set-claim-permission).

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url https://api.p2p.org/api/v1/polkadot/westend/staking/pool/set-claim-permission \
    --header 'accept: application/json' \
    --header 'authorization: Bearer <token>' \
    --header 'content-type: application/json' \
    --data '
  {
    "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
    "permission": "PermissionlessAll",
    "extended": false
  }
  '
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/set-claim-permission",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        permission: "PermissionlessAll",
        extended: false,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/set-claim-permission",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
          "permission": "PermissionlessAll",
          "extended": False,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  		"permission":          "PermissionlessAll",
  		"extended":            false,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/set-claim-permission", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main stash account address which keeps tokens for bonding.

* `permission` — state of the permission to grant:

  * `Permissioned` — only you can claim, bond or withdraw rewards. If this level of permission is set, an additional [claiming payout request](/docs/staking-polkadot#3-create-claim-payout-request) is needed.
  * `PermissionlessCompound` — compounding of rewards (claim and then bond) on your behalf is permitted.
  * `PermissionlessWithdraw` — withdrawing of rewards (claim and then keep as a free balance) on your behalf is permitted.
  * `PermissionlessAll` — claiming, bonding and withdrawing rewards on your behalf are permitted.

* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata in the response.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0xa404160200165874de804160c3cd013d9b6f4bba864657c4c2168a542f78ff14a0253873190200000000",
        "createdAt": "2023-08-24T08:23:18.830Z"
      },
      "error": {}
    }
  ```
</CodeGroup>

* `unsignedTransaction` — unsigned transaction in hex format. Sign the transaction and submit it to the blockchain to perform the called action.

* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.

### 3. Create claiming payout request

Unlike direct staking, after the rewards are distributed to the nomination pool by a validator, each pool member has to claim their part manually. Since that, to bond, compound, or withdraw your rewards, you may need to perform an additional claiming payout request.

Whether it is required depends on the claim rewards permissions you [set in step 2](/docs/staking-polkadot#2-create-set-permission-request) :

* For `PermissionlessAll`, the step is optional.
* For `Permissioned`, the step is necessary, as you are the only one who can claim the rewards.
* For `PermissionlessCompound` and `PermissionlessWithdraw`, the step is required if you want to withdraw and compound your rewards accordingly.

To create a claim payout request:

1. Send a POST request to [/api/v1/polkadot/\{network}/staking/pool/claim-payout](/reference/polkadot-pool-claim-payout).

   Example request (for `westend` network):

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
       --url https://api.p2p.org/api/v1/polkadot/westend/staking/pool/claim-payout \
       --header 'accept: application/json' \
       --header 'authorization: Bearer <token>' \
       --header 'content-type: application/json' \
       --data '
  {
    "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
    "extended": false
  }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/claim-payout",
    {
      method: "POST",
      headers: {
        "accept": "application/json",
        "authorization": "Bearer <token>",
        "content-type": "application/json",
      },
      body: JSON.stringify({
        stashAccountAddress: "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
        extended: false,
      }),
    }
  );
  const data = await response.json();
  console.log(data);
  ```

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

  response = requests.post(
      "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/claim-payout",
      headers={
          "accept": "application/json",
          "authorization": "Bearer <token>",
          "content-type": "application/json",
      },
      json={
          "stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
          "extended": False,
      },
  )
  print(response.json())
  ```

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

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

  func main() {
  	payload := map[string]interface{}{
  		"stashAccountAddress": "5H6ryBWChC5w7eaQ4GZjo329sEnhvjetSr6MBEt42mZ5tPw5",
  		"extended":            false,
  	}
  	body, _ := json.Marshal(payload)
  	req, _ := http.NewRequest("POST", "https://api.p2p.org/api/v1/polkadot/westend/staking/pool/claim-payout", bytes.NewBuffer(body))
  	req.Header.Set("accept", "application/json")
  	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>

* `stashAccountAddress` — main stash account address which keeps tokens for bonding.
* `extended` — optional boolean parameter (`true` or `false`) indicating whether to include additional metadata in the response.

Example response:

<CodeGroup>
  ```json theme={null}
  {
      "result": {
        "unsignedTransaction": "0xa404160100cc7cb7325ad1208212e2d8ee41a7572e816d53ac1bcac1be5df433486819213c0200000000",
        "createdAt": "2023-08-24T08:23:18.830Z"
      }
    }
  ```
</CodeGroup>

* `unsignedTransaction` — unsigned transaction in hex format. Sign the transaction and submit it to the blockchain to perform the called action.
* `createdAt` — timestamp of the transaction in the ISO 8601 format.

2. [Sign and broadcast](/docs/signing-transaction-polkadot) the `unsignedTransaction` to the Polkadot network.


## Related topics

- [Staking API reference](/reference/polkadot-staking-bond.md)
- [Withdrawal](/docs/withdrawal-polkadot.md)
