Account — API reference
Who am I, what is my balance, where do I send money.
| Method | Path | Summary |
|---|---|---|
GET | /v1/account | Account information |
PATCH | /v1/account | Edit the account’s display name |
GET | /v1/balance | Balances only |
GET | /v1/deposit-addresses | Deposit addresses for this account |
GET | /v1/ledger | The account’s ledger statement |
GET | /v1/account/addresses | The account’s address book |
POST | /v1/account/addresses | Save an address |
DELETE | /v1/account/addresses/{entryId} | Remove an address |
GET | /v1/account/stats | Order analytics, aggregated server-side |
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.
Account information
GET /v1/account · getAccount
Auth: API key (HMAC) or bootstrap token.
Identity, balances, deposit addresses, the limits in force and lifetime counters.
This is the endpoint a CatFee-compatible facade maps GET /v1/account onto.
Also readable with a bootstrap token (Authorization: Bearer abt_…), so the signup
flow can poll for the first confirmed deposit without an API key.
Responses
| Status | Meaning |
|---|---|
200 | OK |
401 | Missing, malformed or rejected credentials. |
429 | Too many requests. |
500 | Something broke on our side. |
Response fields (Account)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
brand | string | yes | The brand this account belongs to. Accounts are not shared across brands. |
network | enum: mainnet, nile | yes | The environment this account belongs to. An account, its ledger and its keys do not span environments: a Nile account is a separate account on the api-nile.<brand-domain> host. |
owner_address | string | null | The address that signed the challenge this account was created with; the root of recovery. null only for legacy accounts created before the challenge model. | |
label | string | null | The same value as display_name, under the name this field has always had. New clients should read display_name; this one is not going away. | |
display_name | string | null | The account’s own title, chosen by its owner and editable with PATCH /v1/account. null when it has none, in which case a UI shows the shortened owner_address instead of an internal id. | |
status | enum: unfunded, active, suspended, closed | yes | |
balance_sun | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
balance_usdt | integer (int64) | USDT balance in the token’s smallest unit (6 decimals). | |
reserved_sun | integer (int64) | Held against in-flight orders. Not spendable. | |
deposit_addresses | array of object (DepositAddress) | yes | |
deposit_addresses[].currency | enum: TRX, USDT | yes | |
deposit_addresses[].address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
deposit_addresses[].memo | string | null | Always null since 2026-09-26: every account has an address of its own, so no memo is needed and any memo is ignored. Kept so existing clients do not break. | |
deposit_addresses[].confirmations_required | integer | Blocks waited before the deposit is credited. | |
deposit_addresses[].contract | string | null | The TRC-20 contract accepted at this address (USDT row only; null for TRX). | |
deposit_addresses[].rate_now | null | object | USDT row only. The current SunSwap (or fixed) TRX-per-USDT rate BEFORE the spread, cached 60 s. null when no rate is available right now; the deposit is still accepted and the worker prices it at credit time. Indicative: the credit uses the rate the worker reads when it credits, not this one. | |
deposit_addresses[].rate_now.trx_per_usdt | string | yes | |
deposit_addresses[].rate_now.source | enum: sunswap_v3, fixed_env | yes | |
deposit_addresses[].rate_now.at | string (date-time) | yes | |
deposit_addresses[].spread_bps | integer | null | USDT row only: basis points taken off the rate (5 = 0.05 %). | |
deposit_addresses[].min | string | null | USDT row only: smallest credited USDT deposit; smaller ones are held (held_below_min). | |
deposit_addresses[].max | string | null | USDT row only: largest auto-credited USDT deposit; larger ones are held (held_for_review). | |
limits | object | ||
limits.max_order_energy | integer | ||
limits.max_batch_receivers | integer | ||
limits.orders_per_second | integer | ||
totals | object | Lifetime counters. Informational; not a substitute for the ledger. | |
totals.deposited_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.spent_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.refunded_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.orders_created | integer | ||
totals.energy_delegated | integer (int64) | ||
created_at | string (date-time) | yes |
Example 200 response, from the contract (illustrative values — live numbers come from the API):
{
"id": "acc_01J9Z4K2M7Q8",
"brand": "tenergy.me",
"network": "mainnet",
"label": "Acme payments",
"status": "active",
"balance_sun": 1250400000,
"balance_usdt": 0,
"reserved_sun": 0,
"deposit_addresses": [{"currency":"TRX","address":"TDepositAddressExample1111111111111"}],
"limits": {"max_order_energy":3000000,"max_batch_receivers":100,"orders_per_second":30},
"totals": {
"deposited_sun": 5000000000,
"spent_sun": 3749600000,
"refunded_sun": 0,
"orders_created": 1842,
"energy_delegated": 119730000
},
"created_at": "2026-04-02T09:11:00.000Z"
}
Edit the account’s display name
PATCH /v1/account · updateAccount
Auth: Dashboard session cookie + X-CSRF-Token.
The account’s own title, shown wherever the account is named. null clears it and the
display falls back to the shortened owner address — never to an internal id.
A dashboard session operation, and the account’s owner: the title is what every member sees and what support reads back in a ticket. It is a setting; nothing about who may reach what changes here.
Request body
JSON (AccountPatch), required.
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | null | The account’s title. Trimmed; must not be blank and must carry no control characters. null clears it. |
Responses
| Status | Meaning |
|---|---|
200 | Updated |
400 | Malformed request — bad JSON, unknown field, wrong type. |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
422 | Syntactically valid but semantically impossible. |
500 | Something broke on our side. |
Response fields (Account)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
brand | string | yes | The brand this account belongs to. Accounts are not shared across brands. |
network | enum: mainnet, nile | yes | The environment this account belongs to. An account, its ledger and its keys do not span environments: a Nile account is a separate account on the api-nile.<brand-domain> host. |
owner_address | string | null | The address that signed the challenge this account was created with; the root of recovery. null only for legacy accounts created before the challenge model. | |
label | string | null | The same value as display_name, under the name this field has always had. New clients should read display_name; this one is not going away. | |
display_name | string | null | The account’s own title, chosen by its owner and editable with PATCH /v1/account. null when it has none, in which case a UI shows the shortened owner_address instead of an internal id. | |
status | enum: unfunded, active, suspended, closed | yes | |
balance_sun | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
balance_usdt | integer (int64) | USDT balance in the token’s smallest unit (6 decimals). | |
reserved_sun | integer (int64) | Held against in-flight orders. Not spendable. | |
deposit_addresses | array of object (DepositAddress) | yes | |
deposit_addresses[].currency | enum: TRX, USDT | yes | |
deposit_addresses[].address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
deposit_addresses[].memo | string | null | Always null since 2026-09-26: every account has an address of its own, so no memo is needed and any memo is ignored. Kept so existing clients do not break. | |
deposit_addresses[].confirmations_required | integer | Blocks waited before the deposit is credited. | |
deposit_addresses[].contract | string | null | The TRC-20 contract accepted at this address (USDT row only; null for TRX). | |
deposit_addresses[].rate_now | null | object | USDT row only. The current SunSwap (or fixed) TRX-per-USDT rate BEFORE the spread, cached 60 s. null when no rate is available right now; the deposit is still accepted and the worker prices it at credit time. Indicative: the credit uses the rate the worker reads when it credits, not this one. | |
deposit_addresses[].rate_now.trx_per_usdt | string | yes | |
deposit_addresses[].rate_now.source | enum: sunswap_v3, fixed_env | yes | |
deposit_addresses[].rate_now.at | string (date-time) | yes | |
deposit_addresses[].spread_bps | integer | null | USDT row only: basis points taken off the rate (5 = 0.05 %). | |
deposit_addresses[].min | string | null | USDT row only: smallest credited USDT deposit; smaller ones are held (held_below_min). | |
deposit_addresses[].max | string | null | USDT row only: largest auto-credited USDT deposit; larger ones are held (held_for_review). | |
limits | object | ||
limits.max_order_energy | integer | ||
limits.max_batch_receivers | integer | ||
limits.orders_per_second | integer | ||
totals | object | Lifetime counters. Informational; not a substitute for the ledger. | |
totals.deposited_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.spent_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.refunded_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
totals.orders_created | integer | ||
totals.energy_delegated | integer (int64) | ||
created_at | string (date-time) | yes |
Balances only
GET /v1/balance · getBalance
Auth: API key (HMAC).
A deliberately small response for callers that poll before every order. Cheaper than
/account and on the read rate-limit budget.
Responses
| Status | Meaning |
|---|---|
200 | OK |
401 | Missing, malformed or rejected credentials. |
429 | Too many requests. |
500 | Something broke on our side. |
Response fields (Balance)
| Field | Type | Required | Description |
|---|---|---|---|
balance_sun | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
balance_usdt | integer (int64) | ||
reserved_sun | integer (int64) | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. | |
available_sun | integer (int64) | yes | balance_sun - reserved_sun. This is what an order can draw on. |
as_of | string (date-time) | yes |
Example 200 response, from the contract (illustrative values — live numbers come from the API):
{
"balance_sun": 1250400000,
"balance_usdt": 0,
"reserved_sun": 0,
"available_sun": 1250400000,
"as_of": "2026-09-11T18:04:05.123Z"
}
Deposit addresses for this account
GET /v1/deposit-addresses · listDepositAddresses
Auth: API key (HMAC).
The account’s own deposit address: a TRON address that belongs to this account alone, so
no memo is needed (memo is always null). Two rows, same address: TRX, and USDT
(TRC-20, contract), which the ledger credits as TRX at rate_now minus spread_bps,
between min and max USDT. The address is issued on the first read if the account has none yet.
A deposit is credited after the configured number of block confirmations
(confirmations_required), and produces a balance.credited webhook.
Support can replace the address (never the customer; at most once per
rotation.min_interval_days and rotation.max_per_window times per
rotation.window_days). A replaced address is listed under retired and still credits
until credited_until (rotation.retired_credit_days after it was retired).
Responses
| Status | Meaning |
|---|---|
200 | OK |
401 | Missing, malformed or rejected credentials. |
429 | Too many requests. |
500 | Something broke on our side. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
data | array of object (DepositAddress) | yes | |
data[].currency | enum: TRX, USDT | yes | |
data[].address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
data[].memo | string | null | Always null since 2026-09-26: every account has an address of its own, so no memo is needed and any memo is ignored. Kept so existing clients do not break. | |
data[].confirmations_required | integer | Blocks waited before the deposit is credited. | |
data[].contract | string | null | The TRC-20 contract accepted at this address (USDT row only; null for TRX). | |
data[].rate_now | null | object | USDT row only. The current SunSwap (or fixed) TRX-per-USDT rate BEFORE the spread, cached 60 s. null when no rate is available right now; the deposit is still accepted and the worker prices it at credit time. Indicative: the credit uses the rate the worker reads when it credits, not this one. | |
data[].rate_now.trx_per_usdt | string | yes | |
data[].rate_now.source | enum: sunswap_v3, fixed_env | yes | |
data[].rate_now.at | string (date-time) | yes | |
data[].spread_bps | integer | null | USDT row only: basis points taken off the rate (5 = 0.05 %). | |
data[].min | string | null | USDT row only: smallest credited USDT deposit; smaller ones are held (held_below_min). | |
data[].max | string | null | USDT row only: largest auto-credited USDT deposit; larger ones are held (held_for_review). | |
retired | array of object | Addresses this account used before, newest first. | |
retired[].address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
retired[].retired_at | string (date-time) | yes | |
retired[].credited_until | string (date-time) | yes | A transfer to this address in a block after this instant is not credited automatically; contact support. |
rotation | object | Who may replace the address, and how often. | |
rotation.by | enum: support | yes | |
rotation.min_interval_days | integer | yes | |
rotation.max_per_window | integer | yes | |
rotation.window_days | integer | yes | |
rotation.retired_credit_days | integer | yes |
Example 200 response, from the contract (illustrative values — live numbers come from the API):
{
"data": [
{
"currency": "TRX",
"address": "TDepositAddressExample1111111111111",
"memo": null,
"confirmations_required": 19
}
],
"retired": [
{
"address": "TRetiredAddressExample111111111111",
"retired_at": "2026-09-20T10:00:00.000Z",
"credited_until": "2026-10-20T10:00:00.000Z"
}
],
"rotation": {
"by": "support",
"min_interval_days": 7,
"max_per_window": 3,
"window_days": 90,
"retired_credit_days": 30
}
}
The account’s ledger statement
GET /v1/ledger · listLedger
Auth: Dashboard session cookie + X-CSRF-Token.
Every journal that moved this account’s balance, newest first: deposits, order charges,
refunds and the rest. amount_sun / amount_usdt are the net effect on the balance —
positive when it went up. kind=deposit is the deposit history of the top-up screen.
A deposit appears here once it is credited, i.e. after confirmations_required
block confirmations; a transfer still confirming is not listed yet. sender and
block_number are null on deposits credited before 2026-09-25.
Dashboard session only (member role viewer or above). No API-key scope opens it:
the ledger shows senders and transaction ids that no key-readable endpoint shows today,
and extending balance.read to it is an access decision that has not been taken.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
kind | query | enum: deposit, all | ||
limit | query | integer | ||
cursor | query | string | Opaque cursor from a previous response’s next_cursor. |
Responses
| Status | Meaning |
|---|---|
200 | OK |
400 | Malformed request — bad JSON, unknown field, wrong type. |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
500 | Something broke on our side. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
data | array of object (LedgerEntry) | yes | |
data[].id | string | yes | The ledger journal id. |
data[].kind | enum: deposit, order_charge, order_refund, referral_payout, subscription_fee, subscription_usage, reserve_fee, invoice, withdrawal, adjustment | yes | |
data[].amount_sun | integer (int64) | yes | Net effect on the TRX balance in SUN; negative for a charge. |
data[].amount_usdt | integer (int64) | yes | Net effect on the USDT balance in the token’s smallest unit. |
data[].order_id | string | null | yes | The order a charge or refund belongs to. |
data[].deposit | null | object | yes | Set for kind = deposit, null otherwise. |
data[].deposit.txid | string | null | yes | The deposit transaction hash. |
data[].deposit.sender | string | null | yes | The address the TRX came from; null on deposits credited before 2026-09-25. |
data[].deposit.block_number | integer | null | yes | |
data[].deposit.status | enum: credited, pending_rate, held_below_min, held_for_review | yes | credited for every journal. With kind=deposit, USDT deposits the worker saw but did not credit are listed too (first page only): held_below_min, held_for_review or pending_rate, with amount_sun 0 — nothing was credited. |
data[].deposit.confirmations_required | integer | yes | |
data[].deposit.asset | enum: TRX, USDT | ||
data[].deposit.usdt_amount | string | null | USDT received (decimal string); null for TRX. | |
data[].deposit.rate | string | null | SUN credited per 1 USDT, after the spread; null for TRX and held rows. | |
data[].deposit.rate_source | string | null | Where the rate came from (fixed_env, sunswap_v3@<block>, …); null for TRX. | |
data[].deposit.spread_bps | integer | null | ||
data[].created_at | string (date-time) | yes | |
next_cursor | string | null | yes |
Example 200 response, from the contract (illustrative values — live numbers come from the API):
{
"data": [
{
"id": "jrn_01K5Y8Q2V9M3ZP4T7R1A2B3C4D",
"kind": "order_charge",
"amount_sun": -3900000,
"amount_usdt": 0,
"order_id": "ord_01K5Y8Q2V9M3ZP4T7R1A2B3C4E",
"deposit": null,
"created_at": "2026-09-25T10:12:04.000Z"
},
{
"id": "jrn_01K5Y7A1B2C3D4E5F6G7H8J9K0",
"kind": "deposit",
"amount_sun": 50000000,
"amount_usdt": 0,
"order_id": null,
"deposit": {
"txid": "9f3c1e7a2b4d6f8091a3c5e7f9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7",
"sender": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"block_number": 61000123,
"status": "credited",
"confirmations_required": 19
},
"created_at": "2026-09-25T09:58:40.000Z"
}
],
"next_cursor": null
}
The account’s address book
GET /v1/account/addresses · listAddressBook
Auth: Dashboard session cookie + X-CSRF-Token.
Receivers this account saved for reuse, newest first. At most limit (100) entries.
Dashboard session only (member role viewer or above). No API-key scope opens it
yet; opening it to balance.read keys is an access decision that has not been taken.
Responses
| Status | Meaning |
|---|---|
200 | OK |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
500 | Something broke on our side. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
data | array of object (AddressBookEntry) | yes | |
data[].id | string | yes | |
data[].label | string | yes | |
data[].address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
data[].created_at | string (date-time) | yes | |
data[].updated_at | string (date-time) | yes | |
limit | integer | yes | |
used | integer | yes |
Example 200 response, from the contract (illustrative values — live numbers come from the API):
{
"data": [
{
"id": "adr_01K5Y9B7C8D9E0F1G2H3J4K5M6",
"label": "Payouts hot wallet",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"created_at": "2026-09-25T10:20:00.000Z",
"updated_at": "2026-09-25T10:20:00.000Z"
}
],
"limit": 100,
"used": 1
}
Save an address
POST /v1/account/addresses · saveAddressBookEntry
Auth: Dashboard session cookie + X-CSRF-Token.
Adds address under label. The address is unique per account: saving one that is
already in the book replaces its label, answers 200 with the existing entry and uses
no slot. A new address on a full book is 3019 address_book_full.
Dashboard session, member role editor or above, with X-CSRF-Token.
Request body
JSON (AddressBookRequest), required.
| Field | Type | Required | Description |
|---|---|---|---|
label | string | yes | Trimmed; 1–64 characters after trimming. |
address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
Example request body, from the contract (illustrative values):
{"label":"Payouts hot wallet","address":"TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"}
Responses
| Status | Meaning |
|---|---|
200 | The address was already saved; its label was replaced. |
201 | Saved as a new entry. |
400 | Malformed request — bad JSON, unknown field, wrong type. |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
409 | 3019 address_book_full — details.limit, details.used. |
500 | Something broke on our side. |
Response fields (AddressBookEntry)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
label | string | yes | |
address | string | yes | Base58Check TRON address (starts with T, 34 characters). |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes |
Remove an address
DELETE /v1/account/addresses/{entryId} · deleteAddressBookEntry
Auth: Dashboard session cookie + X-CSRF-Token.
Frees the slot immediately. An id of another account answers 404, like an id that
does not exist. Dashboard session, member role editor, with X-CSRF-Token.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
entryId | path | string | yes |
Responses
| Status | Meaning |
|---|---|
204 | Removed. No body. |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
404 | No such object, or it belongs to another account. The two are not distinguished. |
500 | Something broke on our side. |
Order analytics, aggregated server-side
GET /v1/account/stats · getAccountStats
Auth: API key (HMAC) or dashboard session cookie + X-CSRF-Token.
What the Analytics screen draws, computed next to the data rather than by summing
orders in the page. Covers orders created in [from, to):
| field | what is counted |
|---|---|
orders | every order, whatever its status |
energy | delivered energy of energy orders that reached the chain (delegated … reclaimed): delivered_amount, else amount; failed and refunded orders add none |
spent_sun | total_amount_sun − refunded_amount_sun of every order, activation included |
avg_price_sun_per_65k | the unit price those energy orders were sold at, weighted by delivered energy, × 65,000, rounded to a whole SUN; null without energy |
Days and hours are UTC shifted by utc_offset_minutes, so the page can ask for its
visitor’s calendar. series has one row per day of the range, zeros included.
weekday_hour[d][h] counts orders on ISO weekday d + 1 (Monday first) at hour h.
Retention: 13 months. A from older than that is clamped to the retention start;
clamped is true and requested_from echoes what was asked. Defaults: to = now,
from = to − 30 days. to must be after from (2001 otherwise).
API key scope orders.read (the aggregates are sums over the orders that scope
already lists), or a dashboard session with member role viewer.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string (date-time) | ||
to | query | string (date-time) | ||
bucket | query | enum: day | ||
utc_offset_minutes | query | integer |
Responses
| Status | Meaning |
|---|---|
200 | OK |
400 | Malformed request — bad JSON, unknown field, wrong type. |
401 | Missing, malformed or rejected credentials. |
403 | Authenticated, but this key is not allowed to do it. |
429 | Too many requests. |
500 | Something broke on our side. |
Response fields (AccountStats)
| Field | Type | Required | Description |
|---|---|---|---|
from | string (date-time) | yes | The start actually used |
to | string (date-time) | yes | |
requested_from | string (date-time) | yes | |
clamped | boolean | yes | True when from was older than the retention window and was moved forward. |
retention_months | integer | yes | |
bucket | enum: day | yes | |
utc_offset_minutes | integer | yes | |
totals | object | yes | |
totals.orders | integer | yes | |
totals.energy | integer | yes | |
totals.spent_sun | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
totals.avg_price_sun_per_65k | integer | null | yes | |
series | array of object | yes | |
series[].date | string (date) | yes | |
series[].orders | integer | yes | |
series[].energy | integer | yes | |
series[].spent_sun | integer (int64) | yes | An amount in SUN (1 TRX = 1 000 000 SUN). Always an integer. |
weekday_hour | array of array of integer | yes | Seven rows (Monday first) of 24 hourly order counts. |
top_receivers | array of object | yes | |
top_receivers[].receiver | string | yes | Base58Check TRON address (starts with T, 34 characters). |
top_receivers[].orders | integer | yes | |
top_receivers[].energy | integer | yes | |
top_receivers[].spent_sun | integer (int64) | yes | 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):
{
"from": "2026-09-23T00:00:00.000Z",
"to": "2026-09-25T00:00:00.000Z",
"requested_from": "2026-09-23T00:00:00.000Z",
"clamped": false,
"retention_months": 13,
"bucket": "day",
"utc_offset_minutes": 0,
"totals": {"orders":3,"energy":196000,"spent_sun":11760000,"avg_price_sun_per_65k":3900000},
"series": [
{"date":"2026-09-23","orders":1,"energy":65000,"spent_sun":3900000},
{"date":"2026-09-24","orders":2,"energy":131000,"spent_sun":7860000}
],
"weekday_hour": [[0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]],
"top_receivers": [
{
"receiver": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"orders": 2,
"energy": 131000,
"spent_sun": 7860000
}
]
}