GET /apiv2/pricing
通用价格端点,可在单个响应中返回包含动态时间段的所有服务价格。
履行期间价格可能会变动
此端点返回的价格可能会在订单处理过程中发生变动。能量提供商可能会拒绝委托请求,在这种情况下,Netts 会自动将订单路由至下一个可用的提供商。Netts 不仅致力于提供最具竞争力的价格,还致力于确保可靠的能量供应——因此订单可能会以高于报价的价格履行。这仅适用于 300,000 能量单位及以上的订单。
推荐
这是推荐使用的价格端点。它取代了将被弃用的旧版 /apiv2/prices 端点。
端点 URL
GET https://netts.io/apiv2/pricing请求头
| 请求头 | 必填 | 描述 | 取值 |
|---|---|---|---|
| X-API-KEY | 是 | 您的 API 密钥 | string |
| X-Real-IP | 是 | 白名单中的 IP 地址 | IP 地址 |
| X-Format | 否 | 响应格式(默认:完整 JSON) | now, compact, short, short1h, count |
查询参数
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| services | string | all | 以逗号分隔的筛选列表,指定要包含的服务 |
可用服务
| 服务 | 描述 |
|---|---|
energy_1h | 1 小时能量委托价格 |
energy_5m | 5 分钟能量委托价格 |
host | Host 能量委托费率 |
aml | AML 地址检查价格 |
bandwidth | Bandwidth 租赁价格 —— 选择性加入:仅在通过 ?services=bandwidth 显式请求时返回(不属于默认响应的一部分) |
请求示例
cURL — 完整响应
curl -X GET https://netts.io/apiv2/pricing \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"cURL — 按服务筛选
# 仅 energy 1h 价格
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 价格
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 租赁价格(选择性加入 —— 必须显式请求)
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
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 — 筛选服务
params = {"services": "energy_1h,aml"}
response = requests.get(url, headers=headers, params=params)响应结构
顶级字段
| 字段 | 类型 | 描述 |
|---|---|---|
| success | boolean | 成功请求返回 true |
| version | string | API 版本(例如 "2.1") |
| timestamp | string | ISO 8601 UTC 格式的服务器时间 |
| data | object | 响应有效负载 |
数据字段
| 字段 | 类型 | 描述 |
|---|---|---|
| data.trx_rate_usd | number | 当前 TRX/USD 汇率 |
| data.units_meta | object | 机器可读的单位换算信息 |
| data.services | object | 包含价格数据的所请求服务映射 |
单位元数据
允许客户端以编程方式在各单位之间进行换算:
{
"units_meta": {
"sun": {"base": "trx", "multiplier": 1000000},
"trx": {"base": "trx", "multiplier": 1},
"usdt": {"base": "usdt", "multiplier": 1}
}
}从 SUN 换算为 TRX:trx_price = sun_price / units_meta.sun.multiplier
服务通用字段
每个服务都包含以下字段:
| 字段 | 类型 | 描述 |
|---|---|---|
| unit | string | 价格单位(sun、trx、usdt) |
| pricing_type | string | 如何解析该服务(见下文) |
| description | string | 人类可读的描述 |
| cache_ttl | integer | 此数据刷新的频率(秒) |
计价类型
pricing_type 字段告知客户端如何解析每个服务:
| 类型 | 结构 | 使用者 |
|---|---|---|
periodic | 包含基于时间的价格的 periods[] 数组 | energy_1h, energy_5m |
flat_rates | 包含具名费率键的 rates{} 对象 | host |
provider_based | 包含提供商数据的 providers{} 对象 | aml |
tiered_by_amount_and_period | 按数量范围划分的 tiers[],每个都包含 periods[] | bandwidth |
服务:energy_1h / energy_5m
pricing_type: periodic
| 字段 | 类型 | 描述 |
|---|---|---|
| current_period | string | 当前有效时间段的标识(slug) |
| periods[] | array | 所有计价时间段(动态,从数据库加载) |
| periods[].id | string | 唯一时间段标识符(slug) |
| periods[].label | string | 人类可读的时间段名称 |
| periods[].start | string | 时间段开始时间(HH:MM UTC) |
| periods[].end | string | 时间段结束时间(HH:MM UTC) |
| periods[].is_current | boolean | 该时间段当前是否处于激活状态 |
| periods[].price | integer | 每能量单位的价格(以 SUN 计) |
| periods[].tiers | array|null | 基于用量的计价阶梯(见阶梯) |
动态时间段
时间段的数量、时间范围、标签和价格全部都是动态的并在服务端进行管理。切勿对时间段 ID 或数量进行硬编码。请始终遍历 periods 数组。
服务:host
pricing_type: flat_rates
| 字段 | 类型 | 描述 |
|---|---|---|
| rates.standard_65k | number | 65k 能量的标准费率(TRX) |
| rates.standard_131k_initial | number | 131k 能量的标准费率,初始激活(TRX) |
| rates.frequent_65k | number | 65k 能量的高频费率(TRX) |
| rates.frequent_131k | number | 131k 能量的高频费率(TRX) |
服务:aml
pricing_type: provider_based
| 字段 | 类型 | 描述 |
|---|---|---|
| providers | object | AML 提供商映射(动态,可能会变动) |
| providers[name].price | number | 检查价格(以 USDT 计) |
| providers[name].price_trx | number | 按当前汇率换算为 TRX 的检查价格 |
| providers[name].available | boolean | 提供商是否有可用配额 |
动态提供商
AML 提供商从数据库加载。可能会出现新的提供商,或者现有的提供商可能变得不可用。请始终遍历 providers 对象。
服务:bandwidth
pricing_type: tiered_by_amount_and_period
选择性加入与访问权限
Bandwidth 价格仅在通过 ?services=bandwidth 显式请求时返回——它不属于默认响应的一部分。Bandwidth 租赁端点本身需按申请开通;请联系技术支持获取访问权限。参见 Bandwidth 租赁。
Bandwidth 租赁价格取决于订单数量(单位阶梯)、租赁时长(例如 5m / 1h)、当天时间窗口(UTC)和星期几。基础价格单位为每单位 SUN;在基础价格之上,可能会收取固定的附加费(以 TRX 计)——所有数值均在响应中返回。
响应中同时提供了便捷视图(tiers —— 当前时间窗口/星期的价格)和完整网格(windows + schedule —— 每个星期几对应的每个时间窗口)。
自适应格式 —— 请勿硬编码
计价网格完全由数据驱动且可能随时变动:时间窗口的数量、它们的标签、它们的开始/结束时间、租赁时长集合(可能会添加或删除新的时长)、数量阶梯、星期几明细以及价格本身。客户端必须遍历返回的数组(windows、schedule、tiers、periods)并按值进行匹配——切勿假设固定的数量、固定的标签、固定的时间或固定的时长 ID。以此方式编写的代码在时间表发生变动时仍可正常工作。
| 字段 | 类型 | 描述 |
|---|---|---|
| unit | string | sun_per_unit |
| window | string | 当前时间窗口标签(UTC) |
| current_day_of_week | integer | 当前星期几,ISO 1=周一 … 7=周日(UTC) |
| tiers[] | array | 当前时间窗口/星期的数量阶梯(便捷视图;结构与 schedule 内部相同) |
| windows[] | array | 所有时间窗口名录(可能会增加/缩减/位移) |
| windows[].label | string | 时间窗口标签 |
| windows[].start / .end | string | 时间窗口开始/结束 HH:MM UTC(时间窗口可能会跨越午夜,即 start > end) |
| schedule[] | array | 完整网格 —— 每个(星期几 × 时间窗口)对应一项 |
| schedule[].day_of_week | integer | ISO 星期几 1…7 |
| schedule[].window | string | 时间窗口标签(匹配某个 windows[].label) |
| schedule[].period_start / .period_end | string | HH:MM UTC |
| schedule[].is_current | boolean | 当前生效的分段为 true |
| schedule[].tiers[] | array | 该分段的数量阶梯 |
| tiers[].amount_min | integer | 阶梯下限(包含) |
| tiers[].amount_max | integer|null | 阶梯上限(不包含)。null = 无限制 |
| tiers[].periods[] | array | 阶梯内各租赁时长的价格 |
| tiers[].periods[].id | string | 租赁时长 ID(例如 5m、1h) —— 可能会变动/扩充 |
| tiers[].periods[].rental_seconds | integer | 时长长度(秒) |
| tiers[].periods[].price | integer | 每 Bandwidth 单位的价格(以 SUN 计) |
| surcharges | object | 客户端价格的固定附加项(TRX) —— 见下文 |
| limits | object | 订单限制:min_units、max_units |
附加费
| 字段 | 类型 | 描述 |
|---|---|---|
| surcharges.small_order_threshold_units | integer | amount 低于此值的订单将收取小额订单附加费 |
| surcharges.small_order_surcharge_trx | number | 小额委托订单额外添加的费用(TRX) —— 用于链上委托 + 回收的补偿 |
| surcharges.trx_send_surcharge_trx | number | 通过发送 TRX 履行订单时额外添加的费用(TRX) —— 用于 TRX 转账的补偿 |
响应示例
{
"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 包含了**每个(星期几 × 时间窗口)**组合的条目 —— 遍历它可以渲染完整的价格日历。恰好有一项的 is_current: true。
客户端逻辑(计算订单价格)
使用 tiers 获取“当前时刻的价格”。要查询其他时间的价格,请通过星期几 + 其 [period_start, period_end) 包含该时间的窗口选择匹配的 schedule 条目(请注意当 start > end 时窗口可能会跨越午夜),然后使用其对应的 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).集中化与动态性
Bandwidth 价格、时间窗口、星期几明细和附加费均在服务端(数据库)进行管理并可能会发生变动。请始终从响应中遍历 windows、schedule、tiers 和 periods 并按值进行匹配——切勿对数量、标签、时间或时长 ID 进行硬编码。SUB-user 加价不适用于 Bandwidth。
阶梯
目前所有时间段的 tiers 均为 null。当启用基于用量的阶梯计价时,该字段将包含一个阶梯对象数组:
{
"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"
}
]
}阶梯模式结构
| 字段 | 类型 | 描述 |
|---|---|---|
| min_energy | integer | 该阶梯的最小能量数量(包含) |
| max_energy | integer|null | 该阶梯的最大能量数量(包含)。null = 无限制 |
| price | integer | 该阶梯每能量单位的价格(以 SUN 计) |
| label | string | 阶梯标识符 |
客户端逻辑
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紧凑响应格式
使用 X-Format 请求头可获取紧凑的文本响应。这些响应返回来自 energy_1h 的当前有效时间段价格。
X-Format: now / compact / short
curl -H "X-API-KEY: your_key" -H "X-Format: now" https://netts.io/apiv2/pricing<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
格式相同,但不包含时间段标签和单价。
curl -H "X-API-KEY: your_key" -H "X-Format: short1h" https://netts.io/apiv2/pricing65k=<X.XXX> TRX (<X.XX>$), 131k=<X.XXX> TRX (<X.XX>$), 1m=<X.XXX> TRX (<X.XX>$)X-Format: count
针对 1、2、3、5、10、20 笔订单的批量订单定价。
curl -H "X-API-KEY: your_key" -H "X-Format: count" https://netts.io/apiv2/pricing1-<X.XXX> TRX (<X.XX>$), 2-<X.XXX> TRX (<X.XX>$), ...计算公式
TRX cost = (price_sun / units_meta.sun.multiplier) x energy_amount
USD cost = TRX_cost x trx_rate_usdSUB-User 加价
SUB-user 会自动接收已应用其父级加价后的价格。API 始终返回已认证用户的最终价格——无需在客户端进行计算。
错误响应
错误可能来自具有不同格式的两个层级。您的客户端应同时处理这两者。
应用程序错误(来自 API)
应用程序级别的错误使用标准的 success/error 格式:
无效服务 (400)
{
"success": false,
"error": {
"code": 4002,
"message": "Unknown services: invalid_service"
}
}身份验证错误 (401)
在缺少 API 密钥或 IP 不在白名单中时由应用程序返回:
{
"detail": {
"code": -1,
"msg": "Invalid API key or IP not in whitelist"
}
}格式差异
身份验证错误使用 FastAPI 原生的 detail 格式,而非 success/error 结构。这是因为该错误在请求到达应用程序逻辑之前便已抛出。
用户未找到 (404)
{
"detail": {
"code": -1,
"msg": "User not found"
}
}服务器内部错误 (500)
{
"success": false,
"error": {
"code": 5001,
"message": "Failed to retrieve pricing data"
}
}网关错误(来自 Kong)
这些错误由 API 网关在请求到达应用程序之前返回。它们使用 Kong 自身的格式:
超出速率限制 (429)
{
"message": "API rate limit exceeded"
}网关超时 (504)
{
"message": "An invalid response was received from the upstream server"
}错误代码参考
| 代码 | 描述 | HTTP 状态 | 来源 |
|---|---|---|---|
-1 | 未提供 API 密钥 | 401 | App |
-1 | 无效的 API 密钥或 IP 不在白名单中 | 401 | App |
-1 | 用户未找到 | 404 | App |
4002 | ?services= 参数中存在未知服务 | 400 | App |
5000 | 服务器内部错误 | 500 | App |
5001 | 获取价格数据失败 | 500 | App |
5002 | 紧凑格式的价格数据不可用 | 500 | App |
- | 超出 API 速率限制 | 429 | Kong |
推荐的客户端错误处理
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}")从 /apiv2/prices 迁移
| 方面 | /apiv2/prices(旧版) | /apiv2/pricing(新版) |
|---|---|---|
| 时间段 | 5 个固定时间段 | 从数据库动态加载 |
| 价格阶梯 | 3 个硬编码阶梯 | 单一价格 + 未来的 tiers |
| 时长类型 | 不可用 | energy_5m |
| AML 价格 | 独立端点 | 通过 ?services=aml 包含 |
| Host 价格 | 混合在响应中 | 独立的 host 服务 |
| 服务筛选 | 不可用 | ?services= 参数 |
| 单位换算 | 未记录文档 | 响应中包含 units_meta |
| 缓存信息 | 未记录文档 | 每个服务包含 cache_ttl |
| 响应格式 | {"status": "success", ...} | {"success": true, "version": "2.1", "data": {...}} |
速率限制
适用与 /apiv2/prices 相同的速率限制(在 Kong 网关中配置)。
注意事项
- 所有能量价格均以 SUN 为单位 —— 请使用
units_meta进行换算 - Host 价格以 TRX 为单位
- AML 价格以 USDT 为单位,并包含 TRX 换算
- 所有时间均为 UTC 时间
- 使用每个服务的
cache_ttl了解数据刷新的频率 - 使用
pricing_type确定如何解析每个服务 - 时间段、提供商、费率和所有数值均为动态的 —— 切勿对其进行硬编码
- Bandwidth 计价为选择性加入(
?services=bandwidth),使用带有surcharges的tiered_by_amount_and_period,并且不受 SUB-user 加价影响