Skip to content

GET /apiv2/pricing

Universal pricing endpoint that returns all service prices in a single response with dynamic time periods.

Price may change during fulfillment

The price returned by this endpoint may change while an order is being processed. An energy provider can decline a delegation request, in which case Netts automatically routes the order to the next available provider. Netts is committed not only to offering the most competitive price, but also to ensuring a reliable energy supply — therefore an order may be fulfilled at a higher price than quoted. This applies only to orders of 300,000 energy units and above.

Recommended

This is the recommended pricing endpoint. It replaces the legacy /apiv2/prices endpoint which will be deprecated.

Endpoint URL

GET https://netts.io/apiv2/pricing

Request Headers

HeaderRequiredDescriptionValues
X-API-KEYYesYour API keystring
X-Real-IPYesIP address from whitelistIP address
X-FormatNoResponse format (default: full JSON)now, compact, short, short1h, count

Query Parameters

ParameterTypeDefaultDescription
servicesstringallComma-separated filter of services to include

Available Services

ServiceDescription
energy_1h1-hour energy delegation prices
energy_5m5-minute energy delegation prices
hostHost energy delegation rates
amlAML address check prices
bandwidthBandwidth rental prices — opt-in: returned only when explicitly requested via ?services=bandwidth (not part of the default response)

Example Requests

cURL — Full Response

bash
curl -X GET https://netts.io/apiv2/pricing \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip"

cURL — Filter by Services

bash
# Only energy 1h prices
curl -X GET "https://netts.io/apiv2/pricing?services=energy_1h" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip"

# Energy 1h + AML
curl -X GET "https://netts.io/apiv2/pricing?services=energy_1h,aml" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip"

# Host prices only
curl -X GET "https://netts.io/apiv2/pricing?services=host" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip"

# Bandwidth rental prices (opt-in — must be requested explicitly)
curl -X GET "https://netts.io/apiv2/pricing?services=bandwidth" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip"

Python

python
import requests

url = "https://netts.io/apiv2/pricing"
headers = {
    "X-API-KEY": "your_api_key",
    "X-Real-IP": "your_whitelisted_ip"
}

response = requests.get(url, headers=headers)
data = response.json()

if data.get("success"):
    print(f"API version: {data['version']}")
    print(f"TRX/USD rate: {data['data']['trx_rate_usd']}")

    services = data["data"]["services"]

    for svc_name, svc_data in services.items():
        pricing_type = svc_data.get("pricing_type")
        print(f"\n--- {svc_name} ({pricing_type}) ---")

        if pricing_type == "periodic":
            for period in svc_data["periods"]:
                marker = " <-- current" if period["is_current"] else ""
                print(f"  {period['label']}: {period['price']} {svc_data['unit']}{marker}")

        elif pricing_type == "flat_rates":
            for rate, price in svc_data["rates"].items():
                print(f"  {rate}: {price} {svc_data['unit']}")

        elif pricing_type == "provider_based":
            for name, info in svc_data["providers"].items():
                status = "available" if info["available"] else "unavailable"
                print(f"  {name}: {info['price']} {svc_data['unit']} - {status}")

Python — Filter Services

python
params = {"services": "energy_1h,aml"}
response = requests.get(url, headers=headers, params=params)

Response Structure

Top-Level Fields

FieldTypeDescription
successbooleantrue for successful requests
versionstringAPI version (e.g. "2.1")
timestampstringServer time in ISO 8601 UTC
dataobjectResponse payload

Data Fields

FieldTypeDescription
data.trx_rate_usdnumberCurrent TRX/USD exchange rate
data.units_metaobjectMachine-readable unit conversion info
data.servicesobjectMap of requested services with pricing data

Units Meta

Allows clients to programmatically convert between units:

json
{
    "units_meta": {
        "sun": {"base": "trx", "multiplier": 1000000},
        "trx": {"base": "trx", "multiplier": 1},
        "usdt": {"base": "usdt", "multiplier": 1}
    }
}

To convert from SUN to TRX: trx_price = sun_price / units_meta.sun.multiplier

Service Common Fields

Every service includes these fields:

FieldTypeDescription
unitstringPrice unit (sun, trx, usdt)
pricing_typestringHow to parse this service (see below)
descriptionstringHuman-readable description
cache_ttlintegerHow often this data refreshes (seconds)

Pricing Types

The pricing_type field tells clients how to parse each service:

TypeStructureUsed by
periodicperiods[] array with time-based pricesenergy_1h, energy_5m
flat_ratesrates{} object with named rate keyshost
provider_basedproviders{} object with provider dataaml
tiered_by_amount_and_periodtiers[] by amount range, each with periods[]bandwidth

Service: energy_1h / energy_5m

pricing_type: periodic

FieldTypeDescription
current_periodstringSlug of the currently active period
periods[]arrayAll pricing periods (dynamic, loaded from DB)
periods[].idstringUnique period identifier (slug)
periods[].labelstringHuman-readable period name
periods[].startstringPeriod start time (HH:MM UTC)
periods[].endstringPeriod end time (HH:MM UTC)
periods[].is_currentbooleanWhether this period is currently active
periods[].priceintegerPrice per energy unit in SUN
periods[].tiersarray|nullVolume-based pricing tiers (see Tiers)

Dynamic periods

The number of periods, their time ranges, labels, and prices are all dynamic and managed server-side. Do not hardcode period IDs or counts. Always iterate over the periods array.


Service: host

pricing_type: flat_rates

FieldTypeDescription
rates.standard_65knumberStandard rate for 65k energy (TRX)
rates.standard_131k_initialnumberStandard rate for 131k energy, initial activation (TRX)
rates.frequent_65knumberFrequent rate for 65k energy (TRX)
rates.frequent_131knumberFrequent rate for 131k energy (TRX)

Service: aml

pricing_type: provider_based

FieldTypeDescription
providersobjectMap of AML providers (dynamic, may change)
providers[name].pricenumberCheck price in USDT
providers[name].price_trxnumberCheck price converted to TRX at current rate
providers[name].availablebooleanWhether provider has available quota

Dynamic providers

AML providers are loaded from the database. New providers may appear or existing ones may become unavailable. Always iterate over the providers object.


Service: bandwidth

pricing_type: tiered_by_amount_and_period

Opt-in & access

Bandwidth pricing is returned only when explicitly requested via ?services=bandwidth — it is not part of the default response. The bandwidth rental endpoint itself is available by request; contact support for access. See Bandwidth rental.

Bandwidth rental price depends on the order amount (unit tier), the rental period (e.g. 5m / 1h), the time-of-day window (UTC) and the day of week. Base prices are in SUN per unit; on top of the base, fixed surcharges (in TRX) may apply — all values are returned in the response.

The response provides both a convenience view (tiers — prices for the current window/day) and the full grid (windows + schedule — every window across every weekday).

Adaptive format — do not hardcode

The pricing grid is fully data-driven and may change at any time: the number of time windows, their labels, their start/end times, the set of rental periods (new periods may be added or removed), the amount tiers, the weekday breakdown and the prices themselves. Clients must iterate over the returned arrays (windows, schedule, tiers, periods) and match by value — never assume a fixed count, fixed labels, fixed times or fixed period ids. Code written this way keeps working when the schedule changes.

FieldTypeDescription
unitstringsun_per_unit
windowstringCurrent time-of-day window label (UTC)
current_day_of_weekintegerCurrent weekday, ISO 1=Mon … 7=Sun (UTC)
tiers[]arrayAmount tiers for the current window/day (convenience; same shape as inside schedule)
windows[]arrayDirectory of all time-of-day windows (may grow/shrink/shift)
windows[].labelstringWindow label
windows[].start / .endstringWindow start/end HH:MM UTC (a window may cross midnight, i.e. start > end)
schedule[]arrayFull grid — one entry per (weekday × window)
schedule[].day_of_weekintegerISO weekday 17
schedule[].windowstringWindow label (matches a windows[].label)
schedule[].period_start / .period_endstringHH:MM UTC
schedule[].is_currentbooleantrue for the segment active right now
schedule[].tiers[]arrayAmount tiers for this segment
tiers[].amount_minintegerTier lower bound (inclusive)
tiers[].amount_maxinteger|nullTier upper bound (exclusive). null = unlimited
tiers[].periods[]arrayPrices per rental period within the tier
tiers[].periods[].idstringRental period id (e.g. 5m, 1h) — may change/extend
tiers[].periods[].rental_secondsintegerPeriod length in seconds
tiers[].periods[].priceintegerPrice per bandwidth unit in SUN
surchargesobjectFixed additions to the client price (TRX) — see below
limitsobjectOrder limits: min_units, max_units

Surcharges

FieldTypeDescription
surcharges.small_order_threshold_unitsintegerOrders with amount below this value get the small-order surcharge
surcharges.small_order_surcharge_trxnumberAdded (TRX) for small delegation orders — compensation for on-chain delegation + reclaim
surcharges.trx_send_surcharge_trxnumberAdded (TRX) when the order is fulfilled by sending TRX — compensation for the TRX transfer

Example Response

json
{
    "bandwidth": {
        "unit": "sun_per_unit",
        "pricing_type": "tiered_by_amount_and_period",
        "description": "Bandwidth delegation rental",
        "cache_ttl": 30,

        "window": "<current window label>",
        "current_day_of_week": 7,
        "tiers": [
            {
                "amount_min": 400,
                "amount_max": 1000,
                "periods": [
                    {"id": "5m", "rental_seconds": 300,  "price": "<price_sun>"},
                    {"id": "1h", "rental_seconds": 3600, "price": "<price_sun>"}
                ]
            },
            {"amount_min": 1000, "amount_max": 3000, "periods": ["..."]},
            {"amount_min": 3000, "amount_max": null,  "periods": ["..."]}
        ],

        "windows": [
            {"label": "<window label>", "start": "01:00", "end": "09:00"},
            {"label": "<window label>", "start": "14:00", "end": "00:00"}
        ],
        "schedule": [
            {
                "day_of_week": 1,
                "window": "<window label>",
                "period_start": "01:00",
                "period_end": "09:00",
                "is_current": false,
                "tiers": [
                    {"amount_min": 400, "amount_max": 1000, "periods": [
                        {"id": "5m", "rental_seconds": 300, "price": "<price_sun>"},
                        {"id": "1h", "rental_seconds": 3600, "price": "<price_sun>"}
                    ]}
                ]
            }
        ],

        "surcharges": {
            "small_order_threshold_units": 1000,
            "small_order_surcharge_trx": "<trx>",
            "trx_send_surcharge_trx": "<trx>"
        },
        "limits": {"min_units": 400, "max_units": 5000}
    }
}

schedule contains one entry for every (weekday × window) combination — iterate it to render a full price calendar. Exactly one entry has is_current: true.

Client Logic (compute the order price)

Use tiers for "the price right now". To look up a price for another time, pick the matching schedule entry by weekday + the window whose [period_start, period_end) contains the time (remember a window may cross midnight when start > end), then use its tiers.

# price for the current moment:
for tier in bandwidth.tiers:
    if tier.amount_min <= amount < (tier.amount_max or infinity):
        for p in tier.periods:
            if p.id == requested_period:        # match by value, not by index
                base_trx = (p.price / units_meta.sun.multiplier) * amount
if amount < surcharges.small_order_threshold_units:
    base_trx += surcharges.small_order_surcharge_trx      # delegation orders
# TRX-send fulfillment branch instead:
#   trx_branch_trx = base_trx_for_smallest_tier_shortest_period + surcharges.trx_send_surcharge_trx

# price for an arbitrary weekday/time: same logic, but first select the schedule[] entry
# where day_of_week matches and the time falls in [period_start, period_end).

Centralized & dynamic

Bandwidth prices, windows, weekday breakdown and surcharges are managed server-side (DB) and may change. Always iterate windows, schedule, tiers and periods from the response and match by value — do not hardcode counts, labels, times or period ids. SUB-user markups do not apply to bandwidth.


Tiers

Currently tiers is null for all periods. When volume-based pricing is enabled, the field will contain an array of tier objects:

json
{
    "tiers": [
        {
            "min_energy": 0,
            "max_energy": 64999,
            "price": "<price_sun>",
            "label": "standard"
        },
        {
            "min_energy": 65000,
            "max_energy": 130999,
            "price": "<price_sun>",
            "label": "65k"
        },
        {
            "min_energy": 131000,
            "max_energy": 131000,
            "price": "<price_sun>",
            "label": "131k"
        },
        {
            "min_energy": 131001,
            "max_energy": null,
            "price": "<price_sun>",
            "label": "bulk"
        }
    ]
}

Tiers Schema

FieldTypeDescription
min_energyintegerMinimum energy amount for this tier (inclusive)
max_energyinteger|nullMaximum energy amount for this tier (inclusive). null = unlimited
priceintegerPrice per energy unit in SUN for this tier
labelstringTier identifier

Client Logic

if tiers != null:
    find the tier where min_energy <= order_amount <= max_energy
    use that tier's price
else:
    use the flat price field for all order amounts

Compact Response Formats

Use the X-Format header to get compact text responses. These return the current active period price from energy_1h.

X-Format: now / compact / short

bash
curl -H "X-API-KEY: your_key" -H "X-Format: now" https://netts.io/apiv2/pricing
text
<Period>: price=<N> sun, 65k=<X.XXX> TRX (<X.XX>$), 131k=<X.XXX> TRX (<X.XX>$), 1m=<X.XXX> TRX (<X.XX>$)

X-Format: short1h

Same but without period label and per-unit price.

bash
curl -H "X-API-KEY: your_key" -H "X-Format: short1h" https://netts.io/apiv2/pricing
text
65k=<X.XXX> TRX (<X.XX>$), 131k=<X.XXX> TRX (<X.XX>$), 1m=<X.XXX> TRX (<X.XX>$)

X-Format: count

Bulk order pricing for 1, 2, 3, 5, 10, 20 orders.

bash
curl -H "X-API-KEY: your_key" -H "X-Format: count" https://netts.io/apiv2/pricing
text
1-<X.XXX> TRX (<X.XX>$), 2-<X.XXX> TRX (<X.XX>$), ...

Calculation Formula

TRX cost = (price_sun / units_meta.sun.multiplier) x energy_amount
USD cost = TRX_cost x trx_rate_usd

SUB-User Markup

SUB-users automatically receive prices with their parent's markup applied. The API always returns the final price for the authenticated user — no client-side calculation needed.

Error Responses

Errors may come from two layers with different formats. Your client should handle both.

Application Errors (from API)

Application-level errors use the standard success/error format:

Invalid Service (400)

json
{
    "success": false,
    "error": {
        "code": 4002,
        "message": "Unknown services: invalid_service"
    }
}

Authentication Error (401)

Returned by the application when API key is missing or IP is not whitelisted:

json
{
    "detail": {
        "code": -1,
        "msg": "Invalid API key or IP not in whitelist"
    }
}

Different format

Authentication errors use FastAPI's native detail format, not the success/error structure. This is because the error is raised before the request reaches application logic.

User Not Found (404)

json
{
    "detail": {
        "code": -1,
        "msg": "User not found"
    }
}

Internal Server Error (500)

json
{
    "success": false,
    "error": {
        "code": 5001,
        "message": "Failed to retrieve pricing data"
    }
}

Gateway Errors (from Kong)

These errors are returned by the API gateway before the request reaches the application. They use Kong's own format:

Rate Limit Exceeded (429)

json
{
    "message": "API rate limit exceeded"
}

Gateway Timeout (504)

json
{
    "message": "An invalid response was received from the upstream server"
}

Error Code Reference

CodeDescriptionHTTP StatusSource
-1API key not provided401App
-1Invalid API key or IP not in whitelist401App
-1User not found404App
4002Unknown service in ?services= parameter400App
5000Internal server error500App
5001Failed to retrieve pricing data500App
5002Price data unavailable for compact format500App
-API rate limit exceeded429Kong
python
response = requests.get(url, headers=headers)
data = response.json()

if response.status_code == 200 and data.get("success"):
    # Success — process data
    services = data["data"]["services"]
elif response.status_code == 429:
    # Kong rate limit — back off and retry
    retry_after = response.headers.get("Retry-After", "60")
    time.sleep(int(retry_after))
elif "detail" in data:
    # FastAPI auth/validation error
    detail = data["detail"]
    if isinstance(detail, dict):
        print(f"Error {detail.get('code')}: {detail.get('msg')}")
    else:
        print(f"Error: {detail}")
elif "error" in data:
    # Application error
    err = data["error"]
    print(f"Error {err.get('code')}: {err.get('message')}")
else:
    print(f"Unexpected response: {response.status_code}")

Migration from /apiv2/prices

Aspect/apiv2/prices (old)/apiv2/pricing (new)
Periods5 fixedDynamic from DB
Price tiers3 hardcodedSingle price + future tiers
Duration variantsNot availableenergy_5m
AML pricesSeparate endpointIncluded via ?services=aml
Host pricesMixed in responseSeparate host service
Service filteringNot available?services= parameter
Unit conversionUndocumentedunits_meta in response
Cache infoUndocumentedcache_ttl per service
Response format{"status": "success", ...}{"success": true, "version": "2.1", "data": {...}}

Rate Limits

Same rate limits as /apiv2/prices apply (configured in Kong gateway).

Notes

  • All energy prices are in SUN — use units_meta for conversion
  • Host prices are in TRX
  • AML prices are in USDT with TRX conversion included
  • All times are in UTC
  • Use cache_ttl per service to know how often data refreshes
  • Use pricing_type to determine how to parse each service
  • Periods, providers, rates, and all values are dynamic — do not hardcode them
  • Bandwidth pricing is opt-in (?services=bandwidth), uses tiered_by_amount_and_period with surcharges, and is not subject to SUB-user markup