# Pricing — API reference

Source: https://tenergy.me/docs/api/prices
Last updated: 2026-09-27

Price table, quotes and estimates.

| Method | Path | Summary |
|---|---|---|
| `GET` | `/v1/prices` | Current price table |
| `GET` | `/v1/market` | Public energy rental market board |
| `GET` | `/v1/market/history` | One provider's collected price history |
| `GET` | `/v1/orderbook` | The ask ladder for one resource and tier |
| `GET` | `/v1/estimate` | Stateless price estimate |
| `POST` | `/v1/quotes` | Create a binding quote |
| `GET` | `/v1/quotes/{quoteId}` | Read a quote |

Generated from [`openapi.yaml`](https://tenergy.me/openapi.yaml) at build time. Base URL `https://api.tenergy.me/v1`, or `https://api-nile.tenergy.me/v1` on Nile ([Environments](https://tenergy.me/docs/environments)). Every request below is signed as in [Authentication](https://tenergy.me/docs/authentication) unless its **Auth** line says otherwise.

## Current price table

`GET /v1/prices` · `getPrices`

**Auth:** Public — no credentials needed; a request signed with an API key (HMAC) is accepted too.

Everything currently sellable, with the price for each tier and the volume tiers that
apply. Prices move with the time of day, so the response carries the window in which the
quoted numbers hold (`valid_until`), the current pricing period and the whole day's
`schedule` of periods with the `1h` energy price in each.

Use this to render a tariff table. To pin a price for an order, take a quote
(`POST /v1/quotes`) — a price table entry is informational and is **not** binding.

**Switched-off products.** While the `1d` tier is switched off, the energy `1d` row is
listed with `available: false`, its `payment_addresses` entry is omitted, and orders,
quotes and estimates for it answer `2003 tier_unavailable`. While subscriptions are
switched off, `subscriptions_available` is false and new subscriptions are refused with
`409` `3021 subscriptions_unavailable`.

**Public.** No credentials are needed; anonymous calls are limited per source IP. A
signed request is accepted too and is counted against the key's own budget instead.

**The example below is illustrative; live prices come from this endpoint.** It carries
the day-part schedule of 2026-09-25 — energy `1h` from 20 SUN/unit off-peak to 34 SUN/unit
at peak, here read in the 30 SUN/unit late-peak period — and activation at 1,200,000 SUN; it
shows one item only. The bandwidth grid, the long-tier prices and the volume steps are
still being finalised, so the example leaves them out rather than publish a number
that is not final yet. Iterate over `items`; never assume which tiers or resources
appear.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `resource` | query | enum: `energy`, `bandwidth`, `activation` |  | Restrict the response to one resource type. |

### Responses

| Status | Meaning |
|---|---|
| `200` | OK |
| `401` | Missing, malformed or rejected credentials. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`PriceTable`)

| Field | Type | Required | Description |
|---|---|---|---|
| `network` | enum: `mainnet`, `nile` | yes |  |
| `subscriptions_available` | boolean | yes | Whether a subscription can be created now. False while the deployment has subscriptions switched off; existing subscriptions keep running and stay manageable. |
| `as_of` | string (date-time) | yes |  |
| `valid_until` | string (date-time) | yes | When the quoted prices may change. Re-read after this instant; do not cache past it. |
| `period` | object |  | The pricing period currently in force. Periods are configured server-side and their number, labels and boundaries change — iterate, never hardcode. |
| `period.id` | string |  |  |
| `period.label` | string |  |  |
| `period.start` | string |  | HH:MM UTC |
| `period.end` | string |  | HH:MM UTC |
| `schedule` | array of object |  | Every pricing period of the day, ordered by start, with the energy `1h` price in each — enough to draw the whole day's price map in the reader's own time zone. The periods are configured server-side and change over time (a new version applies from its announced instant): iterate, never hardcode their number, ids or bounds. Together they cover the 24 h once. A period whose `end_utc_minute` is below its `start_utc_minute` runs across midnight UTC. Informational, like the rest of this table: a quote is what pins a price. |
| `schedule[].id` | string | yes |  |
| `schedule[].label` | string | yes |  |
| `schedule[].start_utc_minute` | integer | yes | Inclusive start, minutes after 00:00 UTC. |
| `schedule[].end_utc_minute` | integer | yes | Exclusive end, minutes after 00:00 UTC. |
| `schedule[].factor_bps` | integer | yes | The time-of-day factor of this period, basis points (10,000 = ×1.00). |
| `schedule[].price_sun_per_unit` | number \| null | yes | Energy `1h`, SUN per unit, for an order placed in this period, a multiple of 0.01. `null` when the tier is not on sale in that period. |
| `available_energy` | integer (int64) |  | Energy the platform can sell right now — the order book's sellable depth for the `1h` tier, the same figure `GET /orderbook` publishes. `0` while the book is empty. |
| `delivered_today` | integer (int64) |  | Energy delivered on this brand's orders since 00:00 UTC today (sum of `delivered_amount` over confirmed, active, expired and reclaimed orders). A site may show it as "energy for N transfers delivered today" with N = value ÷ 65,000. |
| `payment_addresses` | object |  | Where the no-account "send TRX" path pays, per tier, on this brand: send TRX to the tier's address with the receiving address in the memo (empty memo: the sender), and the transfer becomes an energy order for that receiver, priced when it arrives. The part of a payment that does not buy a whole 1,000-unit step is kept. Keys are tier ids; a tier without a published address is absent, and the object is empty when the brand publishes none. These are the addresses the platform watches, so a listed address is one a transfer can be matched on. The `1d` entry is omitted while that tier is switched off; a transfer that still reaches its address is refunded to the sender minus the network fee, not filled. |
| `available_bandwidth` | integer (int64) |  |  |
| `items` | array of object | yes |  |
| `items[].resource` | enum: `energy`, `bandwidth`, `activation` | yes | `energy` — TRON energy, the resource a TRC-20 transfer consumes. · `bandwidth` — TRON bandwidth (net), consumed by transaction size. · `activation` — one-off account activation; `amount` and `tier` do not apply. |
| `items[].tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `items[].available` | boolean | yes | Whether this row can be bought now. False for energy `1d` while that tier is switched off: the price is shown, an order for it is `2003 tier_unavailable`. |
| `items[].price_sun_per_unit` | integer | yes | SUN per one unit of the resource for the whole tier period. |
| `items[].min_amount` | integer | yes |  |
| `items[].max_amount` | integer | yes |  |
| `items[].volume_tiers` | array of object |  | Cheaper rates above a threshold. The highest matching entry wins. |
| `items[].volume_tiers[].min_amount` | integer | yes |  |
| `items[].volume_tiers[].price_sun_per_unit` | integer | yes |  |
| `activation` | object |  | Cost of activating an inactive receiver, charged on top of an order. |
| `activation.price_sun` | integer (int64) |  | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |

Example `200` response, from the contract (illustrative values — live numbers come from the API):

```json
{
  "network": "mainnet",
  "as_of": "2026-09-11T18:04:05.123Z",
  "valid_until": "2026-09-11T18:09:05.123Z",
  "period": {"id":"peak_late","label":"Late peak","start":"16:00","end":"00:00"},
  "schedule": [
    {
      "id": "drop",
      "label": "Drop",
      "start_utc_minute": 0,
      "end_utc_minute": 60,
      "factor_bps": 13500,
      "price_sun_per_unit": 27
    },
    {
      "id": "off_peak",
      "label": "Off-peak",
      "start_utc_minute": 60,
      "end_utc_minute": 540,
      "factor_bps": 10000,
      "price_sun_per_unit": 20
    },
    {
      "id": "ramp_9",
      "label": "Ramp 09:00",
      "start_utc_minute": 540,
      "end_utc_minute": 660,
      "factor_bps": 11000,
      "price_sun_per_unit": 22
    },
    {
      "id": "ramp_11",
      "label": "Ramp 11:00",
      "start_utc_minute": 660,
      "end_utc_minute": 720,
      "factor_bps": 12000,
      "price_sun_per_unit": 24
    },
    {
      "id": "ramp_12",
      "label": "Ramp 12:00",
      "start_utc_minute": 720,
      "end_utc_minute": 840,
      "factor_bps": 15000,
      "price_sun_per_unit": 30
    },
    {
      "id": "peak",
      "label": "Peak",
      "start_utc_minute": 840,
      "end_utc_minute": 960,
      "factor_bps": 17000,
      "price_sun_per_unit": 34
    },
    {
      "id": "peak_late",
      "label": "Late peak",
      "start_utc_minute": 960,
      "end_utc_minute": 1440,
      "factor_bps": 15000,
      "price_sun_per_unit": 30
    }
  ],
  "available_energy": 412000000,
  "delivered_today": 80600000,
  "available_bandwidth": 1800000,
  "items": [
    {
      "resource": "energy",
      "tier": "1h",
      "price_sun_per_unit": 30,
      "min_amount": 32000,
      "max_amount": 3000000,
      "volume_tiers": []
    }
  ],
  "activation": {"price_sun":1200000}
}
```

## Public energy rental market board

`GET /v1/market` · `getMarket`

**Auth:** Public — no credentials needed; a request signed with an API key (HMAC) is accepted too.

The latest collected 1h / 1d energy price per public provider (worker collector, every
5 min), plus our own row priced by the same service as `GET /v1/prices`. Sorted by
`price_sun_1h` ascending, unpriced providers last; our row (`slug: tenergy`) is placed by
its real price and on a tie sorts behind the competitor. `savings_pct` = 1 − price /
`burn_sun`; `stale` = the price row is older than 15 min (or missing). Anonymous; a
presented key only buys the per-key budget.

### Responses

| Status | Meaning |
|---|---|
| `200` | The board. |
| `401` | Missing, malformed or rejected credentials. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`MarketBoard`)

| Field | Type | Required | Description |
|---|---|---|---|
| `as_of` | string (date-time) | yes |  |
| `burn_sun` | number | yes | SUN burned per energy unit without rental (100). |
| `providers` | array of object | yes |  |
| `providers[].slug` | string | yes |  |
| `providers[].name` | string | yes |  |
| `providers[].rank` | integer \| null | yes | 1 = cheapest 1h price; null when unpriced. |
| `providers[].price_sun_1h` | number \| null | yes |  |
| `providers[].price_sun_1d` | number \| null | yes |  |
| `providers[].savings_pct` | number \| null | yes | (1 − price_sun_1h / burn_sun) × 100, two decimals. |
| `providers[].available_energy` | integer \| null | yes |  |
| `providers[].total_energy` | integer \| null | yes |  |
| `providers[].kinds` | array of enum: `api`, `bot`, `pool`, `market`, `web` | yes |  |
| `providers[].links` | object | yes |  |
| `providers[].links.site` | string \| null |  |  |
| `providers[].links.telegram` | string \| null |  |  |
| `providers[].links.twitter` | string \| null |  |  |
| `providers[].links.github` | string \| null |  |  |
| `providers[].links.docs` | string \| null |  |  |
| `providers[].links.referral` | string \| null |  | Owner's referral link to the provider; null when there is none and on our own row. |
| `providers[].links.logo` | string \| null |  | Provider logo URL verified on its own site (apple-touch-icon, svg icon, icon or og:image answering 200 with an image type); null when none was found and on our own row. |
| `providers[].ts` | string (date-time) \| null | yes |  |
| `providers[].stale` | boolean | yes |  |
| `summary` | object | yes |  |
| `summary.avg_price_sun_1h` | number \| null | yes | Mean 1h price over fresh priced rows. |
| `summary.active_providers` | integer | yes |  |

## One provider's collected price history

`GET /v1/market/history` · `getMarketHistory`

**Auth:** Public — no credentials needed; a request signed with an API key (HMAC) is accepted too.

Ok collector points for one provider, oldest first. Unknown slug = empty series.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `slug` | query | string | yes |  |
| `hours` | query | integer |  |  |

### Responses

| Status | Meaning |
|---|---|
| `200` | The series. |
| `400` | Malformed request — bad JSON, unknown field, wrong type. |
| `401` | Missing, malformed or rejected credentials. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields

| Field | Type | Required | Description |
|---|---|---|---|
| `slug` | string | yes |  |
| `hours` | integer | yes |  |
| `points` | array of object | yes |  |
| `points[].ts` | string (date-time) | yes |  |
| `points[].price_sun_1h` | number \| null | yes |  |
| `points[].price_sun_1d` | number \| null | yes |  |
| `points[].available_energy` | integer \| null | yes |  |

## The ask ladder for one resource and tier

`GET /v1/orderbook` · `getOrderBook`

**Auth:** Public — no credentials.

Guaranteed delivery at a price that rises with size. The platform publishes a ladder of
**levels** - `amount @ price`, cheapest first - and an order simply walks it: the first
units come from the cheapest level, the next from the one above, and so on. A bigger or
a later order pays more per unit, and it is always fillable. There is no "sold out".

Every level carries a `class`, which says how the energy reaches you and nothing about
who supplies it:

| class | what it is |
|---|---|
| `instant` | the platform's own capacity, delivered immediately |
| `market`  | bought for you on the wholesale market |
| `deep`    | the on-chain market, always available, dearest |

Prices are monotonic - a level never undercuts the one before it - and no level is ever
below the published floor. Pass `amount` to get the walk for that size back with the
levels: `fills`, the volume-weighted `unit_price_sun` and the `total_sun`.

Anonymous and cached for a few seconds. This is a price **display**: to pin a price,
take a quote (`POST /v1/quotes`), which also holds the own-capacity part of the ladder
for its lifetime so the same units are not sold twice.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `resource` | query | enum: `energy`, `bandwidth` |  |  |
| `tier` | query | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` |  |  |
| `amount` | query | integer |  | Walk the ladder for this many units and return the fills as well. |

### Responses

| Status | Meaning |
|---|---|
| `200` | OK |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`OrderBook`)

| Field | Type | Required | Description |
|---|---|---|---|
| `resource` | enum: `energy`, `bandwidth` | yes |  |
| `tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `as_of` | string (date-time) | yes |  |
| `valid_until` | string (date-time) | yes | The book is rebuilt every few seconds; do not cache past this instant. |
| `floor_sun` | number | yes | No level is published below this price, SUN per unit. |
| `depth` | integer | yes | Everything the ladder can deliver right now, in units. |
| `levels` | array of object (OrderBookLevel) | yes |  |
| `levels[].price_sun` | number | yes | SUN per unit for this level, a multiple of 0.01. |
| `levels[].amount` | integer | yes | Units available at this price. |
| `levels[].class` | enum: `instant`, `market`, `deep` | yes | How the energy reaches you: `instant` from the platform's own capacity, `market` bought on the wholesale market, `deep` from the on-chain market. Never a supplier name - the book publishes the class and nothing else. |
| `walk` | object (OrderBookWalk) \| null |  | Present only when `amount` was supplied. |
| `walk.amount` | integer | yes | The requested amount, rounded up to the 1,000-unit step. |
| `walk.fills` | array of object (OrderBookFill) | yes |  |
| `walk.fills[].price_sun` | number | yes |  |
| `walk.fills[].amount` | integer | yes |  |
| `walk.fills[].class` | enum: `instant`, `market`, `deep` | yes |  |
| `walk.unit_price_sun` | number | yes | The volume-weighted price over the fills, SUN per unit. |
| `walk.total_sun` | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `walk.complete` | boolean | yes | `false` when the ladder is shallower than the amount asked for. The `fills` then cover only what the book can deliver right now. |
| `walk.outstanding` | integer |  | Units the ladder could not cover. `0` whenever `complete` is true. |
| `cheaper_from` | string (date-time) \| null |  | When the next cheaper pricing period begins, or `null` when the current one is already the cheapest of the day. Render it in the buyer's own clock. |

Example `200` response, from the contract (illustrative values — live numbers come from the API):

```json
{
  "resource": "energy",
  "tier": "1h",
  "as_of": "2026-09-19T18:04:05.123Z",
  "valid_until": "2026-09-19T18:04:08.123Z",
  "floor_sun": 20,
  "depth": 14200000,
  "levels": [
    {"price_sun":30,"amount":1200000,"class":"instant"},
    {"price_sun":34,"amount":3000000,"class":"market"},
    {"price_sun":58,"amount":10000000,"class":"deep"}
  ],
  "walk": null,
  "cheaper_from": "2026-09-20T01:00:00.000Z"
}
```

## Stateless price estimate

`GET /v1/estimate` · `estimateOrder`

**Auth:** Public — no credentials needed; a request signed with an API key (HMAC) is accepted too.

What an order would cost right now, without creating anything and without reserving a
price. Cheap, safe to call on every keystroke.

The example is illustrative — 65,000 energy at the 20 SUN/unit off-peak placeholder —
and live prices come from `GET /v1/prices`.

The estimate is **not binding**: between the estimate and the order the pricing period may
roll over. If you need the number you showed the user to be the number you are charged,
take a quote instead and pass `quote_id` to `POST /v1/orders`, or send `max_price_sun`.

**Public.** Anonymous calls get the retail price and are limited per source IP. A signed
request is priced for its own account, so a contract customer sees the contract price.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `resource` | query | enum: `energy`, `bandwidth`, `activation` | yes |  |
| `amount` | query | integer (int64) | yes | Energy or bandwidth units. |
| `tier` | query | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes |  |
| `receiver` | query | string |  | When given, the estimate includes the activation fee if the address is not yet activated on chain. Without it, `activate_amount_sun` is `0` and the total may be understated for a fresh address. |

### Responses

| Status | Meaning |
|---|---|
| `200` | OK |
| `400` | Malformed request — bad JSON, unknown field, wrong type. |
| `401` | Missing, malformed or rejected credentials. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`Estimate`)

| Field | Type | Required | Description |
|---|---|---|---|
| `resource` | enum: `energy`, `bandwidth`, `activation` | yes | `energy` — TRON energy, the resource a TRC-20 transfer consumes. · `bandwidth` — TRON bandwidth (net), consumed by transaction size. · `activation` — one-off account activation; `amount` and `tier` do not apply. |
| `amount` | integer | yes |  |
| `tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `receiver` | string \| null |  |  |
| `price_sun_per_unit` | integer | yes |  |
| `energy_amount_sun` | integer (int64) |  | Cost of the resource itself, before activation. |
| `activate_amount_sun` | integer (int64) |  | `0` when the receiver is already active or was not supplied. |
| `total_amount_sun` | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `receiver_activated` | boolean \| null |  | `null` when `receiver` was not supplied. |
| `as_of` | string (date-time) | yes |  |

Example `200` response, from the contract (illustrative values — live numbers come from the API):

```json
{
  "resource": "energy",
  "amount": 65000,
  "tier": "1h",
  "receiver": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "price_sun_per_unit": 20,
  "energy_amount_sun": 1300000,
  "activate_amount_sun": 0,
  "total_amount_sun": 1300000,
  "receiver_activated": true,
  "as_of": "2026-09-11T18:04:05.123Z"
}
```

## Create a binding quote

`POST /v1/quotes` · `createQuote`

**Auth:** API key (HMAC).

Pins a price for a short window. Pass the returned `id` as `quote_id` when creating the
order and you are charged exactly `total_amount_sun`, even if the pricing period rolled
over in between.

A quote reserves a price, **not** inventory. If supply runs out before the order is
created, the order fails with `5001 insufficient_supply` and nothing is charged.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `Idempotency-Key` | header | string |  | Client-chosen key making this mutating request safe to retry, 8–128 characters of `A-Z a-z 0-9 . _ : -`. A repeat with the same key and the same body returns the original result; the same key with a different body is rejected with `3010 idempotency_conflict`. Records live for 24 hours. |

### Request body

JSON (`QuoteRequest`), required.

| Field | Type | Required | Description |
|---|---|---|---|
| `resource` | enum: `energy`, `bandwidth`, `activation` | yes | `energy` — TRON energy, the resource a TRC-20 transfer consumes. · `bandwidth` — TRON bandwidth (net), consumed by transaction size. · `activation` — one-off account activation; `amount` and `tier` do not apply. |
| `amount` | integer |  | Required for `energy` and `bandwidth`; ignored for `activation`. |
| `tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `receiver` | string |  | Base58Check TRON address (starts with `T`, 34 characters). |

Example request body, from the contract (illustrative values):

```json
{"resource":"energy","amount":65000,"tier":"1h","receiver":"TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"}
```

### Responses

| Status | Meaning |
|---|---|
| `201` | Quote created |
| `400` | Malformed request — bad JSON, unknown field, wrong type. |
| `401` | Missing, malformed or rejected credentials. |
| `422` | Syntactically valid but semantically impossible. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`Quote`)

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string | yes |  |
| `resource` | enum: `energy`, `bandwidth`, `activation` | yes | `energy` — TRON energy, the resource a TRC-20 transfer consumes. · `bandwidth` — TRON bandwidth (net), consumed by transaction size. · `activation` — one-off account activation; `amount` and `tier` do not apply. |
| `amount` | integer |  |  |
| `tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `receiver` | string \| null |  |  |
| `price_sun_per_unit` | integer |  |  |
| `unit_price_sun` | number |  | The volume-weighted price this quote was struck at, SUN per unit - the exact number behind `energy_amount_sun`, to the 0.01 SUN step. `price_sun_per_unit` is the same value rounded to a whole SUN and is kept for older clients. |
| `fills` | array of object (OrderBookFill) |  | How the quote walks the ask ladder: which part of the amount comes from which class, and at what price. Empty when the amount was priced at a single rate. |
| `fills[].price_sun` | number | yes |  |
| `fills[].amount` | integer | yes |  |
| `fills[].class` | enum: `instant`, `market`, `deep` | yes |  |
| `energy_amount_sun` | integer (int64) |  | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `activate_amount_sun` | integer (int64) |  | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `total_amount_sun` | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `created_at` | string (date-time) | yes |  |
| `expires_at` | string (date-time) | yes | After this instant the quote is dead and an order referencing it is rejected with `3005 quote_expired`. The quote TTL is **120 seconds** — long enough to survive human latency on a quick-buy flow. Read this field rather than assuming the number. |

Example `201` response, from the contract (illustrative values — live numbers come from the API):

```json
{
  "id": "qt_01J9Z5NB2K4R",
  "resource": "energy",
  "amount": 65000,
  "tier": "1h",
  "receiver": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "price_sun_per_unit": 20,
  "energy_amount_sun": 1300000,
  "activate_amount_sun": 0,
  "total_amount_sun": 1300000,
  "created_at": "2026-09-11T18:04:05.123Z",
  "expires_at": "2026-09-11T18:06:05.123Z"
}
```

## Read a quote

`GET /v1/quotes/{quoteId}` · `getQuote`

**Auth:** API key (HMAC).

Returns the quote, including whether it is still usable (`expires_at` in the future).

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `quoteId` | path | string | yes |  |

### Responses

| Status | Meaning |
|---|---|
| `200` | OK |
| `401` | Missing, malformed or rejected credentials. |
| `404` | No such object, or it belongs to another account. The two are not distinguished. |
| `429` | Too many requests. |
| `500` | Something broke on our side. |

#### Response fields (`Quote`)

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string | yes |  |
| `resource` | enum: `energy`, `bandwidth`, `activation` | yes | `energy` — TRON energy, the resource a TRC-20 transfer consumes. · `bandwidth` — TRON bandwidth (net), consumed by transaction size. · `activation` — one-off account activation; `amount` and `tier` do not apply. |
| `amount` | integer |  |  |
| `tier` | enum: `5m`, `15m`, `1h`, `1d`, `3d`, `30d` | yes | Rental period. The API sells `5m` and `1h`; `1d` exists but is switched off. `15m`, `3d` and `30d` are retired and never sold — they stay in the enum only so old orders parse. Check `available` on each `GET /v1/prices` row; a tier that is not available is rejected with `2003 tier_unavailable`. |
| `receiver` | string \| null |  |  |
| `price_sun_per_unit` | integer |  |  |
| `unit_price_sun` | number |  | The volume-weighted price this quote was struck at, SUN per unit - the exact number behind `energy_amount_sun`, to the 0.01 SUN step. `price_sun_per_unit` is the same value rounded to a whole SUN and is kept for older clients. |
| `fills` | array of object (OrderBookFill) |  | How the quote walks the ask ladder: which part of the amount comes from which class, and at what price. Empty when the amount was priced at a single rate. |
| `fills[].price_sun` | number | yes |  |
| `fills[].amount` | integer | yes |  |
| `fills[].class` | enum: `instant`, `market`, `deep` | yes |  |
| `energy_amount_sun` | integer (int64) |  | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `activate_amount_sun` | integer (int64) |  | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `total_amount_sun` | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
| `created_at` | string (date-time) | yes |  |
| `expires_at` | string (date-time) | yes | After this instant the quote is dead and an order referencing it is rejected with `3005 quote_expired`. The quote TTL is **120 seconds** — long enough to survive human latency on a quick-buy flow. Read this field rather than assuming the number. |
