> For the complete documentation index, see [llms.txt](https://tron-energy-doc.crypto-chief.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tron-energy-doc.crypto-chief.com/guides/first-rental.md).

# Your First Rental

## Your First Rental

A complete working script in each language. Fill in two values at the top and run it.

Each one does the whole flow: checks the balance, simulates the transfer to find out what it really needs, buys the energy, and reports what it cost.

{% hint style="info" %}
You need your **Merchant ID** (project UUID) and your **API key**, both from the Dashboard under Project Settings. The API key is the signing secret — it is never sent.
{% endhint %}

{% tabs %}
{% tab title="JavaScript" %}

```javascript
import crypto from "node:crypto";

const MERCHANT = "your-project-uuid";
const API_KEY = "your-api-key";
const BASE = "https://energy.crypto-chief.com";

// The wallet that will SEND the USDT, and the token contract.
const SENDER = "TDijWGe2r6pTxAufDYGcQyx591Wuyvq4xp";
const USDT = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";

// ── signing ──────────────────────────────────────────────────────────────
// Keys sorted, no whitespace. Sign the canonical string, send the same string.

function canonical(body) {
  if (body === null || body === undefined) return "";
  return JSON.stringify(body, Object.keys(body).sort());
}

function sign(body) {
  const payload = Buffer.from(canonical(body)).toString("base64") + API_KEY;
  return crypto.createHash("md5").update(payload).digest("hex");
}

// A GET has no body, so its signature is just the key hashed. Same every time.
const GET_SIG = crypto.createHash("md5").update(API_KEY).digest("hex");

async function get(path) {
  const res = await fetch(BASE + path, {
    headers: { Merchant: MERCHANT, Signature: GET_SIG },
  });
  return res.json();
}

async function post(path, body, extraHeaders = {}) {
  const res = await fetch(BASE + path, {
    method: "POST",
    body: canonical(body),
    headers: {
      "Content-Type": "application/json",
      Merchant: MERCHANT,
      Signature: sign(body),
      ...extraHeaders,
    },
  });
  return res.json();
}

// ── the flow ─────────────────────────────────────────────────────────────

// 1. Can we pay?
const balance = await get("/v1/balance");
console.log(`Balance: $${balance.usd_balance} (${balance.credits_balance} credits)`);

// 2. What does this transfer actually need?
//    Simulating beats guessing: a contract call costs what it costs, and
//    guessing low reverts the transfer with the fee consumed.
const sim = await post("/v1/simulate", {
  owner_address: SENDER,
  contract_address: USDT,
  function_selector: "transfer(address,uint256)",
  parameter: PARAM_HEX, // ABI-encoded (recipient, amount)
  quote: true,          // price it in the same call
});

if (sim.would_fail) {
  throw new Error(`This transfer would fail on chain: ${sim.reason}`);
}

console.log(`Needs ${sim.energy_needed} energy`);
console.log(`Burning it would cost ${sim.burn_price_trx} TRX`);
console.log(`Renting costs ${sim.quote.price_trx} TRX — you keep ${sim.quote.saving_trx}`);

// 3. Buy it, at the price we were just quoted.
const order = await post(
  "/v1/orders",
  { quote_ref: sim.quote.ref },
  { "Idempotency-Key": "my-first-rental-1" }, // reuse this on any retry
);

if (order.needs_attention) {
  // We do not know what happened. Do NOT retry - it may already be delivered.
  throw new Error(`Order ${order.idempotency_key} needs checking. Contact support.`);
}
if (order.status !== "delivered") {
  throw new Error(`Not delivered: ${order.status} — ${order.error}`);
}

console.log(`Delivered ${order.delivered_energy} energy to ${order.receive_address}`);
console.log(`Charged ${order.credits} credits ($${order.price_usd})`);

// 4. Send your USDT now. It uses the delegated energy instead of burning TRX.
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
const MERCHANT = 'your-project-uuid';
const API_KEY  = 'your-api-key';
const BASE     = 'https://energy.crypto-chief.com';

// The wallet that will SEND the USDT, and the token contract.
const SENDER = 'TDijWGe2r6pTxAufDYGcQyx591Wuyvq4xp';
const USDT   = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';

// ── signing ──────────────────────────────────────────────────────────────
// Keys sorted, no whitespace. Sign the canonical string, send the same string.

function canonical(?array $body): string {
    if ($body === null) return '';
    ksort($body);
    return json_encode($body, JSON_UNESCAPED_SLASHES);
}

function sign(?array $body): string {
    return md5(base64_encode(canonical($body)) . API_KEY);
}

function request(string $method, string $path, ?array $body = null, array $extra = []) {
    $headers = ['Merchant: ' . MERCHANT];
    $opts    = [CURLOPT_RETURNTRANSFER => true];

    if ($method === 'POST') {
        $headers[] = 'Content-Type: application/json';
        $headers[] = 'Signature: ' . sign($body);
        $opts[CURLOPT_POST]       = true;
        $opts[CURLOPT_POSTFIELDS] = canonical($body);
    } else {
        // A GET has no body, so its signature is just the key hashed.
        $headers[] = 'Signature: ' . md5(API_KEY);
    }

    $ch = curl_init(BASE . $path);
    curl_setopt_array($ch, $opts + [CURLOPT_HTTPHEADER => array_merge($headers, $extra)]);
    return json_decode(curl_exec($ch), true);
}

// ── the flow ─────────────────────────────────────────────────────────────

// 1. Can we pay?
$balance = request('GET', '/v1/balance');
echo "Balance: \${$balance['usd_balance']} ({$balance['credits_balance']} credits)\n";

// 2. What does this transfer actually need?
//    Simulating beats guessing: a contract call costs what it costs, and
//    guessing low reverts the transfer with the fee consumed.
$sim = request('POST', '/v1/simulate', [
    'owner_address'     => SENDER,
    'contract_address'  => USDT,
    'function_selector' => 'transfer(address,uint256)',
    'parameter'         => PARAM_HEX,  // ABI-encoded (recipient, amount)
    'quote'             => true,       // price it in the same call
]);

if (!empty($sim['would_fail'])) {
    throw new RuntimeException("This transfer would fail on chain: {$sim['reason']}");
}

echo "Needs {$sim['energy_needed']} energy\n";
echo "Burning it would cost {$sim['burn_price_trx']} TRX\n";
echo "Renting costs {$sim['quote']['price_trx']} TRX — you keep {$sim['quote']['saving_trx']}\n";

// 3. Buy it, at the price we were just quoted.
$order = request('POST', '/v1/orders',
    ['quote_ref' => $sim['quote']['ref']],
    ['Idempotency-Key: my-first-rental-1']);  // reuse this on any retry

if (!empty($order['needs_attention'])) {
    // We do not know what happened. Do NOT retry - it may already be delivered.
    throw new RuntimeException("Order {$order['idempotency_key']} needs checking.");
}
if ($order['status'] !== 'delivered') {
    throw new RuntimeException("Not delivered: {$order['status']} — {$order['error']}");
}

echo "Delivered {$order['delivered_energy']} energy to {$order['receive_address']}\n";
echo "Charged {$order['credits']} credits (\${$order['price_usd']})\n";

// 4. Send your USDT now. It uses the delegated energy instead of burning TRX.
```

{% endtab %}

{% tab title="GO" %}

```go
package main

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
)

const (
	merchant = "your-project-uuid"
	apiKey   = "your-api-key"
	base     = "https://energy.crypto-chief.com"

	// The wallet that will SEND the USDT, and the token contract.
	sender = "TDijWGe2r6pTxAufDYGcQyx591Wuyvq4xp"
	usdt   = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
)

// ── signing ──────────────────────────────────────────────────────────────
// json.Marshal sorts map keys, so a map canonicalises for free. Use a map, not
// a struct: struct fields marshal in declaration order.

func sign(canonical []byte) string {
	sum := md5.Sum([]byte(base64.StdEncoding.EncodeToString(canonical) + apiKey))
	return hex.EncodeToString(sum[:])
}

func call(method, path string, body map[string]any, extra map[string]string) (map[string]any, error) {
	var raw []byte
	if body != nil {
		var err error
		if raw, err = json.Marshal(body); err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, base+path, bytes.NewReader(raw))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Merchant", merchant)
	req.Header.Set("Signature", sign(raw)) // a nil body signs the empty string
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	for k, v := range extra {
		req.Header.Set(k, v)
	}

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	out := map[string]any{}
	b, _ := io.ReadAll(res.Body)
	return out, json.Unmarshal(b, &out)
}

func main() {
	// 1. Can we pay?
	balance, err := call("GET", "/v1/balance", nil, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Balance: $%v (%v credits)\n", balance["usd_balance"], balance["credits_balance"])

	// 2. What does this transfer actually need?
	//    Simulating beats guessing: a contract call costs what it costs, and
	//    guessing low reverts the transfer with the fee consumed.
	sim, err := call("POST", "/v1/simulate", map[string]any{
		"owner_address":     sender,
		"contract_address":  usdt,
		"function_selector": "transfer(address,uint256)",
		"parameter":         paramHex, // ABI-encoded (recipient, amount)
		"quote":             true,     // price it in the same call
	}, nil)
	if err != nil {
		log.Fatal(err)
	}
	if failed, _ := sim["would_fail"].(bool); failed {
		log.Fatalf("This transfer would fail on chain: %v", sim["reason"])
	}

	quote := sim["quote"].(map[string]any)
	fmt.Printf("Needs %v energy\n", sim["energy_needed"])
	fmt.Printf("Burning it would cost %v TRX\n", sim["burn_price_trx"])
	fmt.Printf("Renting costs %v TRX — you keep %v\n", quote["price_trx"], quote["saving_trx"])

	// 3. Buy it, at the price we were just quoted.
	order, err := call("POST", "/v1/orders",
		map[string]any{"quote_ref": quote["ref"]},
		map[string]string{"Idempotency-Key": "my-first-rental-1"}) // reuse on retry
	if err != nil {
		log.Fatal(err)
	}

	if needs, _ := order["needs_attention"].(bool); needs {
		// We do not know what happened. Do NOT retry - it may already be delivered.
		log.Fatalf("Order %v needs checking. Contact support.", order["idempotency_key"])
	}
	if order["status"] != "delivered" {
		log.Fatalf("Not delivered: %v — %v", order["status"], order["error"])
	}

	fmt.Printf("Delivered %v energy to %v\n", order["delivered_energy"], order["receive_address"])
	fmt.Printf("Charged %v credits ($%v)\n", order["credits"], order["price_usd"])

	// 4. Send your USDT now. It uses the delegated energy instead of burning TRX.
}
```

{% endtab %}

{% tab title="Python" %}

```python
import base64, hashlib, json, requests

MERCHANT = "your-project-uuid"
API_KEY  = "your-api-key"
BASE     = "https://energy.crypto-chief.com"

# The wallet that will SEND the USDT, and the token contract.
SENDER = "TDijWGe2r6pTxAufDYGcQyx591Wuyvq4xp"
USDT   = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"

# ── signing ──────────────────────────────────────────────────────────────
# Keys sorted, no whitespace. Sign the canonical string, send the same string.

def canonical(body):
    if body is None:
        return ""
    return json.dumps(body, separators=(",", ":"), sort_keys=True)

def sign(body):
    payload = base64.b64encode(canonical(body).encode()).decode() + API_KEY
    return hashlib.md5(payload.encode()).hexdigest()

# A GET has no body, so its signature is just the key hashed. Same every time.
GET_SIG = hashlib.md5(API_KEY.encode()).hexdigest()

def get(path):
    return requests.get(
        BASE + path,
        headers={"Merchant": MERCHANT, "Signature": GET_SIG},
    ).json()

def post(path, body, extra=None):
    return requests.post(
        BASE + path,
        data=canonical(body),
        headers={
            "Content-Type": "application/json",
            "Merchant": MERCHANT,
            "Signature": sign(body),
            **(extra or {}),
        },
    ).json()

# ── the flow ─────────────────────────────────────────────────────────────

# 1. Can we pay?
balance = get("/v1/balance")
print(f"Balance: ${balance['usd_balance']} ({balance['credits_balance']} credits)")

# 2. What does this transfer actually need?
#    Simulating beats guessing: a contract call costs what it costs, and
#    guessing low reverts the transfer with the fee consumed.
sim = post("/v1/simulate", {
    "owner_address": SENDER,
    "contract_address": USDT,
    "function_selector": "transfer(address,uint256)",
    "parameter": PARAM_HEX,   # ABI-encoded (recipient, amount)
    "quote": True,            # price it in the same call
})

if sim.get("would_fail"):
    raise RuntimeError(f"This transfer would fail on chain: {sim['reason']}")

print(f"Needs {sim['energy_needed']} energy")
print(f"Burning it would cost {sim['burn_price_trx']} TRX")
print(f"Renting costs {sim['quote']['price_trx']} TRX — you keep {sim['quote']['saving_trx']}")

# 3. Buy it, at the price we were just quoted.
order = post(
    "/v1/orders",
    {"quote_ref": sim["quote"]["ref"]},
    {"Idempotency-Key": "my-first-rental-1"},   # reuse this on any retry
)

if order.get("needs_attention"):
    # We do not know what happened. Do NOT retry - it may already be delivered.
    raise RuntimeError(f"Order {order['idempotency_key']} needs checking.")
if order["status"] != "delivered":
    raise RuntimeError(f"Not delivered: {order['status']} — {order['error']}")

print(f"Delivered {order['delivered_energy']} energy to {order['receive_address']}")
print(f"Charged {order['credits']} credits (${order['price_usd']})")

# 4. Send your USDT now. It uses the delegated energy instead of burning TRX.
```

{% endtab %}

{% tab title="curl" %}

```bash
MERCHANT="your-project-uuid"
API_KEY="your-api-key"
BASE="https://energy.crypto-chief.com"

SENDER="TDijWGe2r6pTxAufDYGcQyx591Wuyvq4xp"
USDT="TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"

# Sign a JSON body. On macOS: base64 without -w0, and md5 -q instead of md5sum.
sign() {
  printf "%s" "$1" | base64 -w0 \
    | { read -r b64; printf "%s%s" "$b64" "$API_KEY"; } \
    | md5sum | cut -d" " -f1
}

# A GET has no body, so its signature is just the key hashed.
GET_SIG=$(printf "%s" "$API_KEY" | md5sum | cut -d" " -f1)

# 1. Can we pay?
curl -s "$BASE/v1/balance" \
  -H "Merchant: $MERCHANT" \
  -H "Signature: $GET_SIG"

# 2. What does this transfer actually need?
#    The body must be sorted and compact - that is what gets signed and sent.
BODY="{\"contract_address\":\"$USDT\",\"function_selector\":\"transfer(address,uint256)\",\"owner_address\":\"$SENDER\",\"parameter\":\"$PARAM_HEX\",\"quote\":true}"

curl -s "$BASE/v1/simulate" \
  -H "Content-Type: application/json" \
  -H "Merchant: $MERCHANT" \
  -H "Signature: $(sign "$BODY")" \
  -d "$BODY"

# 3. Buy it, using the quote ref from the response above.
BODY="{\"quote_ref\":\"q_7bxk4m2npqrs8tvw3yz5a6c9d1e4f7g2\"}"

curl -s "$BASE/v1/orders" \
  -H "Content-Type: application/json" \
  -H "Merchant: $MERCHANT" \
  -H "Signature: $(sign "$BODY")" \
  -H "Idempotency-Key: my-first-rental-1" \
  -d "$BODY"

# 4. Send your USDT now. It uses the delegated energy instead of burning TRX.
```

{% endtab %}
{% endtabs %}

## What the script does

**Simulates before buying.** For a plain USDT transfer you could skip this and let us size the order from the recipient's balance. For anything else — a contract call, a different token — the simulation is how you find out what it really needs instead of guessing. `quote: true` prices it in the same call, so the energy figure never has to be carried by hand.

**Stops if the transfer would fail.** `would_fail` means the call reverts on chain whatever energy it has. Finding out here costs nothing; finding out by broadcasting costs the whole fee.

**Sends an idempotency key, and reuses it.** If the request times out, send it again with the *same* key and you get the original order back rather than a second purchase.

**Treats `needs_attention` as stop, not retry.** It means we do not know whether the energy was delivered, so retrying is how one transfer gets bought twice.

## Verify it on chain

Open the sender in [TronScan](https://tronscan.org/) and look at its resources. The delegated energy is there for anyone to see.

## If something goes wrong

| You saw                     | What it means                                                                                                                 |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `409 ADDRESS_NOT_ACTIVATED` | That address has never received anything. Call [`/v1/activate`](/api-reference/activate.md), or send it about 1 TRX yourself. |
| `409 NOT_WORTH_RENTING`     | The market moved; burning is cheaper right now. Try again later.                                                              |
| `402 INSUFFICIENT_CREDITS`  | Top up. Nothing was bought.                                                                                                   |
| `401 INVALID_SIGNATURE`     | Check both your `Merchant` value and your signing code — the error does not say which.                                        |
| The transfer failed anyway  | Check bandwidth — a separate resource this does not rent. See [How Energy Works](/getting-started/how-energy-works.md).       |
