Docs menu

Pricing — API reference

Price table, quotes and estimates.

MethodPathSummary
GET/v1/pricesCurrent price table
GET/v1/marketPublic energy rental market board
GET/v1/market/historyOne provider’s collected price history
GET/v1/orderbookThe ask ladder for one resource and tier
GET/v1/estimateStateless price estimate
POST/v1/quotesCreate a binding quote
GET/v1/quotes/{quoteId}Read a quote

Generated from openapi.yaml at build time. Base URL https://api.tenergy.me/v1, or https://api-nile.tenergy.me/v1 on Nile (Environments). Every request below is signed as in 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

NameInTypeRequiredDescription
resourcequeryenum: energy, bandwidth, activationRestrict the response to one resource type.

Responses

StatusMeaning
200OK
401Missing, malformed or rejected credentials.
429Too many requests.
500Something broke on our side.

Response fields (PriceTable)

FieldTypeRequiredDescription
networkenum: mainnet, nileyes
subscriptions_availablebooleanyesWhether a subscription can be created now. False while the deployment has subscriptions switched off; existing subscriptions keep running and stay manageable.
as_ofstring (date-time)yes
valid_untilstring (date-time)yesWhen the quoted prices may change. Re-read after this instant; do not cache past it.
periodobjectThe pricing period currently in force. Periods are configured server-side and their number, labels and boundaries change — iterate, never hardcode.
period.idstring
period.labelstring
period.startstringHH:MM UTC
period.endstringHH:MM UTC
schedulearray of objectEvery 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[].idstringyes
schedule[].labelstringyes
schedule[].start_utc_minuteintegeryesInclusive start, minutes after 00:00 UTC.
schedule[].end_utc_minuteintegeryesExclusive end, minutes after 00:00 UTC.
schedule[].factor_bpsintegeryesThe time-of-day factor of this period, basis points (10,000 = ×1.00).
schedule[].price_sun_per_unitnumber | nullyesEnergy 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_energyinteger (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_todayinteger (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_addressesobjectWhere 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_bandwidthinteger (int64)
itemsarray of objectyes
items[].resourceenum: energy, bandwidth, activationyesenergy — 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[].tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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[].availablebooleanyesWhether 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_unitintegeryesSUN per one unit of the resource for the whole tier period.
items[].min_amountintegeryes
items[].max_amountintegeryes
items[].volume_tiersarray of objectCheaper rates above a threshold. The highest matching entry wins.
items[].volume_tiers[].min_amountintegeryes
items[].volume_tiers[].price_sun_per_unitintegeryes
activationobjectCost of activating an inactive receiver, charged on top of an order.
activation.price_suninteger (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

StatusMeaning
200The board.
401Missing, malformed or rejected credentials.
429Too many requests.
500Something broke on our side.

Response fields (MarketBoard)

FieldTypeRequiredDescription
as_ofstring (date-time)yes
burn_sunnumberyesSUN burned per energy unit without rental (100).
providersarray of objectyes
providers[].slugstringyes
providers[].namestringyes
providers[].rankinteger | nullyes1 = cheapest 1h price; null when unpriced.
providers[].price_sun_1hnumber | nullyes
providers[].price_sun_1dnumber | nullyes
providers[].savings_pctnumber | nullyes(1 − price_sun_1h / burn_sun) × 100, two decimals.
providers[].available_energyinteger | nullyes
providers[].total_energyinteger | nullyes
providers[].kindsarray of enum: api, bot, pool, market, webyes
providers[].linksobjectyes
providers[].links.sitestring | null
providers[].links.telegramstring | null
providers[].links.twitterstring | null
providers[].links.githubstring | null
providers[].links.docsstring | null
providers[].links.referralstring | nullOwner’s referral link to the provider; null when there is none and on our own row.
providers[].links.logostring | nullProvider 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[].tsstring (date-time) | nullyes
providers[].stalebooleanyes
summaryobjectyes
summary.avg_price_sun_1hnumber | nullyesMean 1h price over fresh priced rows.
summary.active_providersintegeryes

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

NameInTypeRequiredDescription
slugquerystringyes
hoursqueryinteger

Responses

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

Response fields

FieldTypeRequiredDescription
slugstringyes
hoursintegeryes
pointsarray of objectyes
points[].tsstring (date-time)yes
points[].price_sun_1hnumber | nullyes
points[].price_sun_1dnumber | nullyes
points[].available_energyinteger | nullyes

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:

classwhat it is
instantthe platform’s own capacity, delivered immediately
marketbought for you on the wholesale market
deepthe 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

NameInTypeRequiredDescription
resourcequeryenum: energy, bandwidth
tierqueryenum: 5m, 15m, 1h, 1d, 3d, 30d
amountqueryintegerWalk the ladder for this many units and return the fills as well.

Responses

StatusMeaning
200OK
429Too many requests.
500Something broke on our side.

Response fields (OrderBook)

FieldTypeRequiredDescription
resourceenum: energy, bandwidthyes
tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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_ofstring (date-time)yes
valid_untilstring (date-time)yesThe book is rebuilt every few seconds; do not cache past this instant.
floor_sunnumberyesNo level is published below this price, SUN per unit.
depthintegeryesEverything the ladder can deliver right now, in units.
levelsarray of object (OrderBookLevel)yes
levels[].price_sunnumberyesSUN per unit for this level, a multiple of 0.01.
levels[].amountintegeryesUnits available at this price.
levels[].classenum: instant, market, deepyesHow 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.
walkobject (OrderBookWalk) | nullPresent only when amount was supplied.
walk.amountintegeryesThe requested amount, rounded up to the 1,000-unit step.
walk.fillsarray of object (OrderBookFill)yes
walk.fills[].price_sunnumberyes
walk.fills[].amountintegeryes
walk.fills[].classenum: instant, market, deepyes
walk.unit_price_sunnumberyesThe volume-weighted price over the fills, SUN per unit.
walk.total_suninteger (int64)yesAn amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
walk.completebooleanyesfalse when the ladder is shallower than the amount asked for. The fills then cover only what the book can deliver right now.
walk.outstandingintegerUnits the ladder could not cover. 0 whenever complete is true.
cheaper_fromstring (date-time) | nullWhen 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

NameInTypeRequiredDescription
resourcequeryenum: energy, bandwidth, activationyes
amountqueryinteger (int64)yesEnergy or bandwidth units.
tierqueryenum: 5m, 15m, 1h, 1d, 3d, 30dyes
receiverquerystringWhen 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

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

Response fields (Estimate)

FieldTypeRequiredDescription
resourceenum: energy, bandwidth, activationyesenergy — 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.
amountintegeryes
tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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.
receiverstring | null
price_sun_per_unitintegeryes
energy_amount_suninteger (int64)Cost of the resource itself, before activation.
activate_amount_suninteger (int64)0 when the receiver is already active or was not supplied.
total_amount_suninteger (int64)yesAn amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
receiver_activatedboolean | nullnull when receiver was not supplied.
as_ofstring (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

NameInTypeRequiredDescription
Idempotency-KeyheaderstringClient-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.

FieldTypeRequiredDescription
resourceenum: energy, bandwidth, activationyesenergy — 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.
amountintegerRequired for energy and bandwidth; ignored for activation.
tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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.
receiverstringBase58Check 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

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

Response fields (Quote)

FieldTypeRequiredDescription
idstringyes
resourceenum: energy, bandwidth, activationyesenergy — 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.
amountinteger
tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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.
receiverstring | null
price_sun_per_unitinteger
unit_price_sunnumberThe 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.
fillsarray 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_sunnumberyes
fills[].amountintegeryes
fills[].classenum: instant, market, deepyes
energy_amount_suninteger (int64)An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
activate_amount_suninteger (int64)An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
total_amount_suninteger (int64)yesAn amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
created_atstring (date-time)yes
expires_atstring (date-time)yesAfter 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

NameInTypeRequiredDescription
quoteIdpathstringyes

Responses

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

Response fields (Quote)

FieldTypeRequiredDescription
idstringyes
resourceenum: energy, bandwidth, activationyesenergy — 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.
amountinteger
tierenum: 5m, 15m, 1h, 1d, 3d, 30dyesRental 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.
receiverstring | null
price_sun_per_unitinteger
unit_price_sunnumberThe 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.
fillsarray 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_sunnumberyes
fills[].amountintegeryes
fills[].classenum: instant, market, deepyes
energy_amount_suninteger (int64)An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
activate_amount_suninteger (int64)An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
total_amount_suninteger (int64)yesAn amount in SUN (1 TRX = 1 000 000 SUN). Always an integer.
created_atstring (date-time)yes
expires_atstring (date-time)yesAfter 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.

    ↑ ↓ to move · Enter to open · Esc to close