POST /apiv2/bandwidth
租赁 TRON Bandwidth 并将其委托给接收地址,租期固定:5 分钟,认证账户还可选择 1 小时。
⚠️ 访问层级。
- 认证账户可在资金池规模和上限范围内租赁任意数量(最高 5000),租期 5 分钟或 1 小时,支持多个并发订单。认证由 Netts 支持团队授予。
- 未认证账户只能单次租赁 400 个单位,租期 5 分钟 — 仅在上一次租赁结束后才允许下一次订单。非 400 数量的请求、1 小时租期的请求,或在首个订单仍处于活跃状态时提交的第二个订单将被拒绝。
端点 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 )) # 在 2 秒窗口内重试保持稳定;或使用您自己的订单 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" ) )
# 每个订单仅生成一次,并在每次重试时重新发送相同的值。
nonce = str(int(time.time() // 2)) # 2 秒时间桶;或您自己的订单 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']}") # 委托交易哈希数组
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 | 代码 | 状态 |
|---|---|---|---|
| 已完成 | 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 | 代码 | 状态 | 结果 |
|---|---|---|---|---|
| 已委托 → 立即回收 | 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..." # 租赁响应中的 orderId
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 单位、租期 5 分钟的订单;更大数量或 1 小时租期需要认证 | 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 秒时间桶;或您自己的订单 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 字符 base64# 然后将其作为标头发送:
-H "X-Idempotency-Key: <base64_key>"在消息中包含 period 至关重要:为同一地址租赁 5 分钟与 1 小时属于不同的订单,必须生成不同的密钥。
**验证。**所提供的
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;请等待后重试。
后付费账户
采用后付费结算的账户与其他账户使用相同的端点、URL、标头和请求正文。不同之处在于订单的支付方式:
- 不从您的充值押金中扣除任何费用。每个已交付的订单都会按照合同中约定的结算货币计入您账户的应付余额。您根据协议按发票付款。
- 您的账户拥有信用额度。只要应付金额在额度范围内,即使充值押金为零也会接受订单。5 分钟和 1 小时的租赁计入相同的 Bandwidth 额度。
- 仅对已交付的服务计费:委托给地址的 Bandwidth,或代为发送的 TRX(
fulfilledBy = trx)。金额与预付费订单相同。 - 被拒绝、未执行、试运行(
test: true)或返回enough(check: true)的订单不产生费用。 - 主动提前回收不会减少应付金额,规则与预付费订单一致。
- 访问层级、数量、时长以及此端点的所有其他规则均与预付费账户相同。
根据申请,Netts 可为账户启用后付费结算。每次响应都会告知订单的支付方式:paymentMode 为 postpaid 或 prepaid。
价格查询(test: true)
{
"amount": 1000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"period": "5m",
"test": true
}{
"detail": {
"code": 10003,
"status": "test",
"msg": "Test run — no on-chain action, no charge",
"data": {
"orderId": "B5M1a2b3c4d5e6f70",
"testAction": "would_delegate",
"wouldCostTRX": 0.7,
"paidTRX": 0,
"bandwidth": 1000,
"period": "5m",
"receiverFreeBandwidth": 600,
"paymentMode": "postpaid"
}
}
}wouldCostTRX 是将要计入您应付余额的金额(单位为 TRX)。不委托任何资源,也不收取费用。
成功下单
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful, 0.700000 TRX, postpaid",
"data": {
"orderId": "B5M0f9e8d7c6b5a41",
"paidTRX": 0.7,
"fulfilledBy": "bandwidth",
"hash": ["<txid>"],
"bandwidth": 1000,
"period": "5m",
"paymentMode": "postpaid",
"totalTRX": "0.700000"
}
}
}| 字段 | 说明 |
|---|---|
| paidTRX | 服务费用(单位为 TRX)。对于后付费账户,不会从充值押金中扣除 |
| paymentMode | postpaid |
| totalTRX | 精确金额,保留 6 位小数 |
所有其他字段,包括 TRX 分支(fulfilledBy = trx、trxSendHash),均与预付费订单相同。
达到信用额度(402)
{
"detail": {
"code": 1004,
"msg": "Postpaid credit limit reached.",
"paymentMode": "postpaid",
"reason": "limit_reached"
}
}订单未执行且不计费。一旦记录了您的付款或提高了额度,将重新接受新订单。
后付费错误代码
| 代码 | HTTP | 说明 |
|---|---|---|
1004 | 402 | 达到后付费信用额度 |
5032 | 503 | 价格暂时不可用 |
5034 | 503 | 计费服务暂时不可用 — 订单未被接受 |
5036 | 503 | 信用检查暂时不可用 — 请稍后重试 |
对于上述所有响应,均未下单且不计费。所有其他代码与预付费订单相同。
说明
- **访问层级:**认证账户可在资金池/上限范围内租赁任意数量,并支持并发订单;未认证账户 — 单次 400 个单位,租期 5 分钟(仅在上一次租赁结束后方可提交下一次订单)。如需认证,请联系 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 秒。