Skip to content

GET /apiv2/pricing

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

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

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"

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

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.


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