POST /apiv2/bandwidth
租赁 TRON Bandwidth 并将其委托给接收地址一段固定时间(5 分钟或 1 小时)。
⚠️ 访问层级。
- 认证账户可在资金池大小和最大限制范围内租赁任意数量(最高 5000),并支持多个并发订单。认证由 Netts 支持团队授予。
- 未认证账户一次只能租赁 400 个单位 — 仅在前一次租赁结束后才允许提交下一个订单。请求 400 以外的金额,或在第一个订单仍处于活动状态时提交第二个订单,都将被拒绝。
端点 URL
POST https://netts.io/apiv2/bandwidth请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
| Content-Type | 是 | application/json |
| X-API-KEY | 是 | 来自 Netts 控制面板的 API 密钥 |
| X-Real-IP | 是 | 来自白名单的 IP 地址 |
| X-Idempotency-Key | 否 | 可选的客户端生成密钥(base64),用于安全重试以避免重复下单。如果省略,服务器将自动生成一个 |
请求体
{
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m"
}参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| amount | 整数 | 是 | 要租赁的 Bandwidth 单位数(最小值:400,最大值:5000) |
| receiveAddress | 字符串 | 是 | 接收 Bandwidth 的 TRON 地址(T…,34 个字符,base58) |
| period | 字符串 | 是 | 租赁时长:"5m"(5 分钟)或 "1h"(1 小时) |
| trx_send | 布尔值 | 否 | 交易保障:如果无可用 Bandwidth,则向该地址发送 TRX 以确保交易仍能顺利完成。仅在 amount = 400 时有效(否则忽略)。默认值为 false |
| check | 布尔值 | 否 | 如果为 true 且接收方已拥有超过 400 的 Bandwidth,则不进行委托且不收取费用(状态为 enough)。默认值为 false |
| test | 布尔值 | 否 | 试运行。如果为 true,将模拟整个下单流程 — 响应会告知您将发生的结果以及将收取的价格 — 不执行任何链上操作且不收取费用。默认值为 false |
请求示例
以下示例还构建并发送了
X-Idempotency-Key,以防止意外重复提交导致创建第二个订单。完整规则请参见幂等性。
cURL
API_KEY="your_api_key"
ADDR="TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AMOUNT=1500
PERIOD="5m"
NONCE=$(( $(date +%s) / 2 )) # stable for retries within a 2s window; or your own order UUID
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
IDEMP=$(printf '%s' "${ADDR}:${AMOUNT}:${PERIOD}:${NONCE}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary | base64)
curl -X POST https://netts.io/apiv2/bandwidth \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-H "X-Real-IP: your_whitelisted_ip" \
-H "X-Idempotency-Key: $IDEMP" \
-d "{\"amount\": $AMOUNT, \"receiveAddress\": \"$ADDR\", \"period\": \"$PERIOD\"}"Python
import time, hmac, hashlib, base64, requests
API_KEY = "your_api_key"
url = "https://netts.io/apiv2/bandwidth"
payload = {
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m",
}
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
# Generate ONCE per order and resend the same value on every retry.
nonce = str(int(time.time() // 2)) # 2s bucket; or your own order UUID
message = f"{payload['receiveAddress']}:{payload['amount']}:{payload['period']}:{nonce}"
idem_key = base64.b64encode(
hmac.new(API_KEY.encode(), message.encode(), hashlib.sha256).digest()
).decode()
headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
"X-Real-IP": "your_whitelisted_ip",
"X-Idempotency-Key": idem_key,
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
detail = data.get("detail", {})
if response.status_code == 200 and detail.get("status") == "completed":
d = detail["data"]
print(f"Order ID: {d['orderId']}")
print(f"Hashes: {d['hash']}") # array of delegation tx hashes
print(f"Bandwidth: {d['bandwidth']} for {d['period']}")
print(f"Cost: {d['paidTRX']} TRX")
else:
print(f"Code: {detail.get('code')} | {detail.get('msg', detail)}")服务包中提供了一个完整的客户端示例(Python + cURL) (handler_bandwidth/doc/client_example/)。
响应
成功 — Bandwidth 已委托 (200 OK)
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "bandwidth",
"hash": ["a1b2c3...", "d4e5f6..."],
"bandwidth": 1500,
"period": "5m"
}
}
}成功 — 发送 TRX 代替 Bandwidth (200 OK,仅限 amount=400 + trx_send=true)
当资金池没有 Bandwidth 且启用了 trx_send 时,将向该地址发送 TRX 以确保交易仍能顺利通过。无论请求的时长如何,在这种情况下均收取固定费用。
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful (sent TRX, bandwidth unavailable)",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "trx",
"trxSendHash": ["<txid>"],
"hash": [],
"bandwidth": 400,
"period": "5m"
}
}
}已充足 — 未扣费 (200 OK,仅限 check=true)
{
"detail": {
"code": 10002,
"status": "enough",
"msg": "enough band for 1 transfer",
"data": { "orderId": "B5M<key14>", "paidTRX": 0, "bandwidth": 400, "period": "5m" }
}
}处理中 — 外部提供商 (202 Accepted)
当订单异步移交给外部提供商时返回。请使用 orderId 轮询状态端点(见下文),直至其完成。
{
"detail": {
"code": 10001,
"status": "processing",
"msg": "Order accepted, processed by an external provider. Poll the status endpoint.",
"data": { "orderId": "B5M<key14>", "bandwidth": 1500, "period": "5m" }
}
}测试运行 (200 OK,仅限 test=true)
模拟整个下单流程。testAction 告知您将要发生的情况,wouldCostTRX 告知将要收取的费用。不委托任何资源,不发送 TRX,不收取任何费用(paidTRX: 0)。
{
"detail": {
"code": 10003,
"status": "test",
"msg": "Test run — no on-chain action, no charge",
"data": {
"orderId": "B5M<...>",
"testAction": "would_delegate",
"wouldCostTRX": "<amount that would be charged in TRX>",
"paidTRX": 0,
"bandwidth": 400,
"period": "5m",
"receiverFreeBandwidth": 600
}
}
}testAction 的取值:would_delegate(将委托 Bandwidth)、would_trx_send(无可用 Bandwidth,amount=400 + trx_send → 将发送 TRX)、enough(接收方已有足够资源,配合 check=true),或 would_error:<reason>(例如 no_bandwidth、not_whitelisted)。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| detail.code | 整数 | 10000 已委托/TRX,10002 已充足,10001 处理中 |
| detail.status | 字符串 | completed / enough / processing / failed |
| detail.data.orderId | 字符串 | 订单 ID,格式为 B5M…(5 分钟)/ B1H…(1 小时)— 用于状态端点 |
| detail.data.paidTRX | 数字 | 以 TRX 计费收取的金额(为 enough 时为 0) |
| detail.data.fulfilledBy | 字符串 | bandwidth(已委托)/ trx(已发送 TRX) |
| detail.data.hash | 数组 | 委托交易哈希(最多 10 个)。始终为数组(TRX 分支为空) |
| detail.data.trxSendHash | 数组 | TRX 转账哈希,仅在 fulfilledBy = trx 时存在 |
| detail.data.bandwidth | 整数 | 已委托的 Bandwidth 单位数 |
| detail.data.period | 字符串 | 租赁时长(5m / 1h) |
状态端点
GET https://netts.io/apiv2/bandwidth/status/{orderId}请求头:X-API-KEY + X-Real-IP(订单必须属于已认证的用户)。
| 订单状态 | HTTP | code | status |
|---|---|---|---|
| 已完成 | 200 | 10000 | completed(包含 hash / trxSendHash) |
| 进行中 | 200 | 10001 | processing |
| 已充足 | 200 | 10002 | enough |
| 失败 | 200 | 5003 | failed |
| 未找到 / 不属于您 | 404 | -1 | — |
回收端点
在其租期结束前,主动回收(取消委托)您的某个已委托订单的 Bandwidth。Bandwidth 会被自动取消委托并返回交易哈希。
POST https://netts.io/apiv2/bandwidth/reclaim/{orderId}请求头:X-API-KEY + X-Real-IP(订单必须属于已认证的用户)。
| 订单状态 | HTTP | code | status | 结果 |
|---|---|---|---|---|
| 已委托 → 立即回收 | 200 | 10004 | reclaimed | reclaimHash(取消委托交易哈希) |
| 已回收 | 200 | 10004 | reclaimed | reclaimHash + 消息 "already reclaimed" |
| 非已委托状态(无可回收内容) | 400 | 5005 | failed | — |
| 回收尚未完成 | 503 | 5003 | failed | 稍后重试 |
| 未找到 / 不属于您 | 404 | -1 | — | — |
curl -X POST https://netts.io/apiv2/bandwidth/reclaim/B5M<...> \
-H "X-API-KEY: your_api_key" -H "X-Real-IP: your_whitelisted_ip"{
"detail": {
"code": 10004,
"status": "reclaimed",
"msg": "Bandwidth reclaimed",
"data": { "orderId": "B5M<...>", "reclaimHash": ["<txid>"] }
}
}import requests
order_id = "B5M..." # the orderId from your rental response
url = f"https://netts.io/apiv2/bandwidth/reclaim/{order_id}"
headers = {"X-API-KEY": "your_api_key", "X-Real-IP": "your_whitelisted_ip"}
resp = requests.post(url, headers=headers)
detail = resp.json()["detail"]
if resp.status_code == 200 and detail["status"] == "reclaimed":
print(f"Reclaimed: {detail['data']['reclaimHash']} ({detail['msg']})")
else:
print(f"Code {detail.get('code')}: {detail.get('msg', detail)}")主动提前回收不退还租赁费用 — 回收仅会在期满前将已委托的 Bandwidth 归还给资金池。
错误响应
认证错误 (401)
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }余额不足 (403)
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient funds" } }校验错误 (400)
{ "detail": { "code": 5004, "status": "failed", "msg": "Bandwidth amount out of range (400..5000)" } }委托失败 / 服务不可用 (503)
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }错误码参考
| 错误码 | 说明 | HTTP 状态 |
|---|---|---|
10000 | 成功(已委托,或已发送 TRX) | 200 |
10000 | 成功(缓存响应) | 208 |
10001 | 已接受,由外部提供商处理中 | 202 |
10002 | 接收方已有足够 Bandwidth(未扣费) | 200 |
10003 | 测试运行 — 结果 + 价格预览,未收取任何费用(test=true) | 200 |
10004 | Bandwidth 已回收(主动取消委托)— 返回 reclaimHash | 200 |
- | 重复请求仍在处理中 | 409 |
-1 | API 密钥无效 / IP 不在白名单中 | 401 |
1004 | 余额不足 | 403 |
1005 | 用户无付款人地址 | 400 |
5004 | 无效的数量/时长(校验失败) | 400 |
5005 | 无可回收内容(订单非已委托状态) | 400 |
5007 | 未认证 — 一次只能租赁一次;前一个订单仍处于活动状态(请等待其结束) | 503 |
5008 | 未认证 — 仅允许 400 单位的订单;更大金额需要认证 | 503 |
5003 | Bandwidth 委托失败 / 不可用 | 503 |
5000 | 服务器内部错误 | 500 |
频率限制
| 周期 | 限制 | 说明 |
|---|---|---|
| 1 秒 | 50 次请求 | 每个 IP 每秒最多 50 次请求 |
超出频率限制 (429)
{ "message": "API rate limit exceeded" }幂等性
发送可选的 X-Idempotency-Key 请求头,以确保意外重复提交不会创建第二个订单 — 将返回原始响应并带有 HTTP 208。如果您不发送该请求头,服务器会在短时间窗口内根据您的请求参数自动派生一个密钥。
如何生成密钥
密钥格式为 base64( HMAC-SHA256( secret, message ) ) — 包含 44 个字符的 base64 字符串,其中:
- secret = 您的 API 密钥(
X-API-KEY); - message = 使用
:拼接的字段 —receiveAddress:amount:period:nonce。
nonce 是在同一逻辑订单的多次重试之间保持稳定,但在不同订单之间有所区别的任意值 — 例如您为该订单保留的 UUID,或粗粒度的时间戳桶。每个订单仅生成一次密钥,并在每次重试时重新发送完全相同的值。
import hmac, hashlib, base64, time
def make_idempotency_key(api_key, receive_address, amount, period, nonce=None):
if nonce is None:
nonce = str(int(time.time() // 2)) # 2-second bucket; or your own order UUID
message = f"{receive_address}:{amount}:{period}:{nonce}"
digest = hmac.new(api_key.encode(), message.encode(), hashlib.sha256).digest()
return base64.b64encode(digest).decode() # 44-char base64# then send it as a header:
-H "X-Idempotency-Key: <base64_key>"在 message 中包含 period 非常重要:为相同地址分别租赁 5m 和 1h 属于不同的订单,必须生成不同的密钥。
**校验。**提供的
X-Idempotency-Key必须是 16–64 个字符的 base64 字符串(字符集为A–Z a–z 0–9 + / = _ -)。格式错误或过长的密钥将被拒绝并返回 HTTP 400(code 5004)。
| 状态码 | 含义 |
|---|---|
| 200 | 处理成功(首次请求) |
| 208 | 已成功处理 — 返回缓存的响应(不重复扣费) |
| 409 | 相同的请求正在处理中 — 请等待,暂勿重试 |
失败后重试。仅缓存成功的结果(
completed/enough)。如果上一次尝试失败或超时(未扣除资金),您可以安全地使用相同的X-Idempotency-Key重试 — 系统会再次尝试该订单,而不是返回旧的错误。当尝试仍在进行中时,您会收到409;请等待后重试。
注意事项
- **访问层级:**认证账户可在资金池/最大限制范围内以并发订单租赁任意数量;未认证账户 — 一次 400 个单位(前一次租赁结束后才可下达下一个订单)。如需认证,请联系 Netts 支持团队。
- **最小值:**400 个单位。**最大值:**每单 5000 个单位(当前配置)。
- 时长:
5m(300 秒)和1h(3600 秒)。租期结束时 Bandwidth 将被自动回收。 - **无缓冲:**严格按照请求的数量进行委托。
- **hash 是一个数组:**单个订单可能会产生多达 10 个委托哈希 — 全部都会被返回。
- **定价:**以 TRX 收费,基于请求的数量和时长;费率可能会因时段而异。请联系支持团队以获取当前价格。
- 小额订单补偿(委托):对于低于 1000 个单位的订单,价格中会增加固定的 0.372 TRX,作为链上委托和回收的补偿。1000 个单位或以上的订单没有此项附加费用。
- **发送 TRX 补偿:**当通过发送 TRX 完成订单时(
fulfilledBy = trx),改为增加固定的 0.268 TRX(作为链上 TRX 转账的补偿)。 - **trx_send:**仅适用于
amount = 400;如果无可用 Bandwidth,则向该地址发送 TRX 以确保交易仍能顺利通过。 - **check:**当接收方已拥有超过 400 的 Bandwidth 时,跳过委托(和扣费)。
- 订单 ID 格式:
B5M…(5 分钟)/B1H…(1 小时)。 - **响应超时:**等待委托时最多约 12 秒;通常为 1–2 秒。