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

# Energy Delegation

> Delegate generated ENERGY to another TRON account without transferring ownership of the frozen TRX.

Delegate generated `ENERGY` to another TRON account without transferring ownership of the underlying frozen TRX.

## What is Energy delegation?

On TRON, every action that touches a smart contract (including TRC-20 transfers, e.g. USDT) consumes `ENERGY`. `ENERGY` is generated by freezing TRX via [`/staking/delegate`](/reference/tron-staking-delegate), the same mechanism used for `BANDWIDTH` and voting power.

Energy delegation lets the account that froze the TRX (the **owner**) share the `ENERGY` it generates with a different account (the **receiver**), without moving the frozen TRX itself and without giving up ownership of it. The owner keeps the frozen balance, its voting rights, and can reclaim the delegated resource at any time after the lock period expires.

This is the pattern used to cover gas costs for a large number of wallets from a single pool of frozen TRX — for example, an exchange or a custodian freezing TRX once and delegating `ENERGY` to hundreds of hot wallets so that each of them can pay for TRC-20 transfers without holding TRX of its own.

<Warning>
  Only `ENERGY` is supported for delegation in the current version. `BANDWIDTH` delegation is not available.
</Warning>

## The full flow

Energy delegation sits between the freeze and unfreeze steps of the regular TRON staking flow:

```
freeze  →  delegate-resource  →  undelegate-resource  →  unfreeze  →  withdraw
```

<Table>
  <thead>
    <tr>
      <th>
        Step
      </th>

      <th>
        Endpoint
      </th>

      <th>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        1. Freeze
      </td>

      <td>
        `/staking/delegate`
      </td>

      <td>
        Freeze TRX and generate `ENERGY` on the owner account
      </td>
    </tr>

    <tr>
      <td>
        2. Delegate resource
      </td>

      <td>
        `/staking/delegate-resource`
      </td>

      <td>
        Delegate generated `ENERGY` from the owner to a receiver account.
      </td>
    </tr>

    <tr>
      <td>
        3. Undelegate resource
      </td>

      <td>
        `/staking/undelegate-resource`
      </td>

      <td>
        Reclaim previously delegated `ENERGY` back to the owner, once the delegation lock period has passed.
      </td>
    </tr>

    <tr>
      <td>
        4. Unfreeze
      </td>

      <td>
        `/staking/undelegate`
      </td>

      <td>
        Unfreeze the owner's TRX
      </td>
    </tr>

    <tr>
      <td>
        5. Withdraw
      </td>

      <td>
        `/staking/withdraw`
      </td>

      <td>
        Claim the unfrozen TRX back to the available balance
      </td>
    </tr>
  </tbody>
</Table>

Steps 1, 4, and 5 are the standard freeze/unfreeze/withdraw operations already described in [Getting Started](/docs/staking-tron) and [Withdrawal](/docs/withdrawal-tron). This guide focuses on steps 2 and 3, which sit in between.

Note that the owner does not have to unfreeze immediately after undelegating. `ENERGY` can be delegated and reclaimed many times over the lifetime of a single frozen balance — unfreezing is only required once the owner wants the underlying TRX back.

## Signing model

As with any other operation on TRON, `/staking/delegate-resource` and `/staking/undelegate-resource` only build and return an **unsigned** transaction — the API never holds or uses your private key. The client is responsible for signing every transaction in the flow (freeze, delegate-resource, undelegate-resource, unfreeze, withdraw) individually with the [P2P Signer SDK](/docs/signer-sdk-overview) and broadcasting it via [/transaction/send](/reference/tron-transaction-send), following the steps described in [Sign and Broadcast Transaction](/docs/signing-transaction-tron).

The owner address that signs the delegate/undelegate-resource transaction must be the same address that froze the TRX (`delegatorAddress`) — the receiver never signs anything as part of this flow.

## 1. Create delegate-resource request

To delegate generated `ENERGY` to a receiver account, send a POST request to [`/api/v1/tron/{network}/staking/delegate-resource`](/reference/tron-staking-delegate-resource).

Example request (for `testnet-nile` network):

```shell theme={null}
curl --request POST \
  --url 'https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/delegate-resource' \
  --header 'accept: application/json' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
    "amount": 1000000,
    "resource": "ENERGY"
}'
```

* `delegatorAddress` — owner account address, i.e. the account that froze the TRX and generated the `ENERGY`.
* `amount` — amount of resource to delegate in SUN. Minimum amount is 1 TRX (1 000 000 SUN)
* `resource` — resource type to delegate. Only `ENERGY` is supported in the current version, defaults to `ENERGY`. Optional.

Example response:

```json theme={null}
{
  "error": null,
  "result": {
    "delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
    "receiverAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
    "amount": 10000000,
    "resource": "ENERGY",
    "lockPeriod": 28800,
    "unsignedTransaction": {
      "visible": false,
      "txID": "b7c4a2f1e6d9083c...",
      "raw_data_hex": "0a...",
      "raw_data": {
        "contract": [
          {
            "parameter": {
              "value": {
                "owner_address": "41da53d324a354aa5924c7117caff3ead97910a5e1",
                "receiver_address": "41700ca9ad5f162f9de000558ff04eef8f99dce7e8",
                "balance": 10000000,
                "resource": "ENERGY"
              },
              "type_url": "type.googleapis.com/protocol.DelegateResourceContract"
            },
            "type": "DelegateResourceContract"
          }
        ],
        "ref_block_bytes": "0e0c",
        "ref_block_hash": "7db974037137d39c",
        "expiration": 1750000200000,
        "timestamp": 1750000140000
      }
    },
    "unsignedTransactionSerialized": "eyJ0eElEIjoidHJ4SWQifQ==",
    "createdAt": "2025-06-03T12:00:00.000Z"
  }
}
```

* `delegatorAddress` — owner account address.
* `receiverAddress` — account address receiving the delegated resource.
* `amount` — amount of resource delegated, in SUN.
* `resource` — resource type delegated: `ENERGY`.
* `lockPeriod` — 28800, i.e. blocks, ≈ 24 h at 3 s per block.
* `unsignedTransaction` — original unsigned transaction object returned by tronWeb.
* `unsignedTransactionSerialized` — unsigned serialized transaction in Base64 format, ready for signing.
* `createdAt` — timestamp of the transaction in the ISO 8601 format.

## Delegation lock

TRON enforces a protocol-level lock on delegated resources: once `ENERGY` has been delegated to a receiver, it cannot be undelegated for **approximately 24 hours** from the moment the delegation transaction is confirmed. This is a network rule, and it applies per delegation — each new `/staking/delegate-resource` call starts its own 24-hour lock for the amount it delegates.

Calling `/staking/undelegate-resource` before the lock period has elapsed will cause the transaction to fail on-chain. Plan any automated re-delegation or rebalancing logic around this window, and track the delegation's confirmation time so you know when it becomes eligible for undelegation.

**The lock is amount-aware. **TRON keeps one lock per (owner, receiver) pair, so an older expired portion can coexist with a freshly locked one. Undelegating within the unlocked part succeeds; only a request reaching into the locked part is rejected.

**The unlock time is machine-readable**.  DelegationLockedException returns both the message and a structured field:

```json theme={null}
"errors": [ { "property": "delegation", "constraints": { "unlocksAt": "2026-08-19T11:48:06.000Z" } } ]
```

Integrators should read `errors[0].constraints.unlocksAt` rather than parsing the message, and use it to schedule the retry instead of polling on a fixed 24-hour timer.

## 2. Create undelegate-resource request

Once the lock period has passed, reclaim the delegated `ENERGY` back to the owner account by sending a POST request to [`/api/v1/tron/{network}/staking/undelegate-resource`](/reference/tron-staking-undelegate-resource).

Example request (for `testnet-nile` network):

```shell theme={null}
curl --request POST \
  --url 'https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/undelegate-resource' \
  --header 'accept: application/json' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
    "amount": 1000000,
    "resource": "ENERGY"
}'
```

* `delegatorAddress` — owner account address that originally delegated the resource.
* `amount` — amount of resource to delegate in SUN. Minimum amount is 1 TRX (1 000 000 SUN)
* `resource` — resource type to reclaim. Only `ENERGY` is supported, defaults to `ENERGY`. Optional.

Example response:

```json theme={null}
{
  "error": null,
  "result": {
    "delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
    "receiverAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
    "amount": 10000000,
    "resource": "ENERGY",
    "unsignedTransaction": {
      "visible": false,
      "txID": "d3f8b1a2c9e6740f...",
      "raw_data_hex": "0a...",
      "raw_data": {
        "contract": [
          {
            "parameter": {
              "value": {
                "owner_address": "41da53d324a354aa5924c7117caff3ead97910a5e1",
                "receiver_address": "41700ca9ad5f162f9de000558ff04eef8f99dce7e8",
                "balance": 10000000,
                "resource": "ENERGY"
              },
              "type_url": "type.googleapis.com/protocol.UnDelegateResourceContract"
            },
            "type": "UnDelegateResourceContract"
          }
        ],
        "ref_block_bytes": "0e0c",
        "ref_block_hash": "7db974037137d39c",
        "expiration": 1750086600000,
        "timestamp": 1750086540000
      }
    },
    "unsignedTransactionSerialized": "eyJ0eElEIjoidHJ4SWQifQ==",
    "createdAt": "2025-06-03T12:00:00.000Z"
  }
}
```

Field descriptions mirror the delegate-resource response above; the only difference is the underlying `UnDelegateResourceContract` type.

## Error codes

`/staking/delegate-resource` and `/staking/undelegate-resource` can return the following `400 Bad request` errors in addition to the standard `401` and `429` responses.

`/staking/delegate-resource` :&#x20;

| Code   | Exception                              | Description                                                                                                                                             |
| ------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 125102 | `InvalidDelegatorAddressException`     | Invalid delegator address provided. Please ensure the address is a valid TRON address format.                                                           |
| 125123 | `InvalidReceiverException`             | Invalid receiver address. The receiver must be a valid TRON address and must differ from the owner address.                                             |
| 125104 | `InvalidFreezeAmountException`         | Freeze amount is below the minimum required threshold (1 TRX = 1,000,000 SUN).                                                                          |
| 125125 | `ResourceNotSupportedException`        | Resource type is not supported. Only ENERGY delegation is available.                                                                                    |
| 125124 | `ExceedsDelegatableMaxException`       | Delegation amount exceeds the maximum delegatable resource for this account. Freeze more TRX or reduce the amount.                                      |
| 125121 | `DelegateResourceTransactionException` | Failed to create the resource delegation transaction. Verify the amount does not exceed the delegatable balance and that the account has frozen ENERGY. |

`/staking/undelegate-resource` :&#x20;

&#x20;

| Code   | Exception                                | Description                                                                                                                       |
| ------ | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 125102 | `InvalidDelegatorAddressException`       | Invalid delegator address provided. Please ensure the address is a valid TRON address format.                                     |
| 125123 | `InvalidReceiverException`               | Invalid receiver address. The receiver must be a valid TRON address and must differ from the owner address.                       |
| 125105 | `InvalidUnfreezeAmountException`         | Unfreeze amount exceeds the available frozen balance or is invalid. Please verify the account's frozen amount.                    |
| 125125 | `ResourceNotSupportedException`          | Resource type is not supported. Only ENERGY delegation is available.                                                              |
| 125126 | `NoActiveDelegationException`            | No active ENERGY delegation found for this account. There is nothing to undelegate.                                               |
| 125127 | `ExceedsDelegatedAmountException`        | Undelegation amount exceeds the currently delegated ENERGY balance. Please reduce the amount.                                     |
| 125128 | `DelegationLockedException`              | Delegation is still locked and cannot be undelegated until the lock period expires.                                               |
| 125122 | `UndelegateResourceTransactionException` | Failed to create the resource undelegation transaction. Locked delegations can only be undelegated after the lock period expires. |

## Testing on the Nile testnet

Before delegating on mainnet, validate the full flow on TRON's Nile testnet using the `testnet-nile` network identifier. Because of the delegation lock, a full round trip through steps will take about 24 hours to complete.

1. **Fund a Nile testnet account.** Use the [Nile faucet](https://nileex.io/join/getJoinPage) to receive test TRX on your account.
2. **Freeze TRX for **`ENERGY`**.** Send a POST request to `/api/v1/tron/testnet-nile/staking/delegate` with `resource: "ENERGY"`, sign, and broadcast the transaction, as described in [Getting Started](/docs/staking-tron).
3. **Delegate the resource.** Send a POST request to:

   ```
   https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/delegate-resource
   ```

   with your `delegatorAddress`, a `receiverAddress` you control (a second Nile testnet account), and the `amount` to delegate.&#x20;
4. **Sign** transaction
5. **Broadcast** via POST `/tron/testnet-nile/transaction/send `
6. **Verify the delegation.** The transaction confirms as DelegateResourceContract; getDelegatedResourceV2(owner, pool) shows the delegation with an expire\_time.
7. **Undelegate the resource. **Once the lock has expired, send a POST request to:
   ```
   https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/undelegate-resource
   ```
   with the same `delegatorAddress`/`receiverAddress` pair and `amount`, then sign and broadcast.

Testnet transactions use the same request/response shapes as mainnet. Only the `network` path parameter and the `api-test.p2p.org` host differ, so code validated on Nile carries over to production without changes.


## Related topics

- [Staking API reference](/reference/tron-staking-delegate.md)
- [Sign and Broadcast Transaction](/docs/signing-transaction-tron.md)
- [Withdrawal](/docs/withdrawal-tron.md)
