Skip to content
Translated page. The English version is the source of truth.

POST /apiv2/order1h ​

通过多个能量供应商创建 1 小时能量租赁订单,支持自动故障转移。

端点 URL ​

POST https://netts.io/apiv2/order1h

请求标头 ​

HeaderRequiredDescription
Content-Type是application/json
X-API-KEY是来自 Netts 控制面板的 API 密钥
X-Real-IP是来自白名单的 IP 地址

请求体 ​

json
{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

请求参数 ​

ParameterTypeRequiredDescription
amountinteger是租赁的 Energy 数量(最小值:61000,最大值:3000000)
receiveAddressstring是接收能量的 TRON 地址(TRC-20 格式)

供应商选择 ​

API 会根据以下条件自动选择最佳能量供应商:

  • 成本效益 - 始终寻找最低可用价格
  • 可用性 - 确保充足的能量储备
  • 可靠性 - 使用成功率高的供应商
  • 速度 - 优先考虑交付时间最快的供应商

示例 ​

cURL ​

bash
curl -X POST https://netts.io/apiv2/order1h \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip" \
  -d '{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
  }'

Python ​

python
import requests

url = "https://netts.io/apiv2/order1h"
headers = {
    "Content-Type": "application/json",
    "X-API-KEY": "your_api_key",
    "X-Real-IP": "your_whitelisted_ip"
}

payload = {
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

response = requests.post(url, headers=headers, json=payload)
data = response.json()

if response.status_code == 200:
    detail = data.get('detail', {})
    order_data = detail.get('data', {})
    print(f"Order ID: {order_data.get('orderId')}")
    print(f"Transaction Hash: {order_data.get('hash')}")
    print(f"Energy Delivered: {order_data.get('energy')}")
    print(f"Cost: {order_data.get('paidTRX')} TRX")
    print(f"Delegate Address: {order_data.get('delegateAddress')}")
else:
    error_detail = data.get('detail', data)
    print(f"Error Code: {error_detail.get('code', 'N/A')}")
    print(f"Error Message: {error_detail.get('msg', error_detail)}")

响应 ​

成功响应 (200 OK) ​

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.23 TRX deducted",
        "data": {
            "orderId": "1H123456",
            "paidTRX": 2.23,
            "hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
            "delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq",
            "energy": 131050
        }
    }
}

响应字段 ​

字段TypeDescription
detail.codeinteger成功订单始终为 10000
detail.msgstring包含扣费金额的成功消息
detail.data.orderIdstring统一订单 ID(格式:1H{request_id})
detail.data.paidTRXnumberTRX 总费用(若地址未激活,则包含激活费)
detail.data.hashstring | null交易哈希。该字段始终存在但可能为空 - 部分供应商不会立即返回哈希。1 分钟后使用 /apiv2/order_check 获取哈希
detail.data.delegateAddressstring代理能量的资源池地址
detail.data.energyinteger能量数量 + 缓冲(通常为 +50)

错误响应 ​

认证错误 (401) ​

json
{
    "detail": "Invalid API key or IP not in whitelist"
}

余额不足 (403) ​

json
{
    "code": 1004,
    "msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}

服务不可用 (503) ​

json
{
    "code": 5003,
    "msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}

供应商错误 (503) ​

json
{
    "code": 5001,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5002,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5004,
    "msg": "Energy provider requires higher minimum amount"
}

内部服务器错误 (500) ​

json
{
    "code": 5000,
    "msg": "Internal server error occurred"
}

错误代码参考 ​

代码DescriptionHTTP 状态码
10000成功200
10000成功(缓存响应)208
-重复请求仍在处理中409
1004余额不足403
5000内部服务器错误500
5001能量供应商不可用503
5002能量供应商不可用503
5003能量服务不可用503
5004未达到能量供应商最低数量要求503

速率限制 ​

以下速率限制适用于此端点(按 IP 地址):

周期限制Description
1 秒50 次请求每秒最多 50 次请求

速率限制响应头 ​

http
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49

超出速率限制 (429) ​

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

幂等性 ​

API 支持幂等性以防止重复处理订单。当您发送多个相同请求时,系统可确保订单仅被处理一次。

幂等性工作原理 ​

请求的唯一性由以下组合决定:

  • 请求时间戳(1 秒窗口)
  • 能量数量
  • 接收地址
  • API 密钥

每个请求都有一个 1 秒的唯一性窗口。为保护系统免遭滥用并确保正确处理,具有相同参数的请求每秒发送频率不能超过一次。

**当前行为:**系统会自动保护客户端免于对已订购的能量进行错误重试。如果您不小心发送了两次相同的请求,您不会被重复扣费。

提供您自己的密钥 ​

您可以通过发送 X-Idempotency-Key 请求头来完全掌控幂等性。当该请求头存在时,仅凭该值决定请求是否重复,上述自动组合将不再使用。当其缺失时,行为保持不变 —— 服务器会为您自动派生密钥。

请求头X-Idempotency-Key
格式严格为 64 位小写十六进制字符 —— SHA-256 摘要
有效期自携带该密钥的首次请求起 24 小时
作用域您的账户。不同账户发送的相同值绝不会返回您的结果

任何其他格式的密钥 —— 带连字符的 UUID、base64、大写十六进制 —— 都会在下单前以及发生任何扣费前被拒绝并返回 400:

json
{
    "detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}

该格式与其他端点不同。/apiv2/withdraw、/apiv2/bandwidth 以及编排器接受 16–64 字符的 base64 密钥。此端点仅接受 64 字符的十六进制摘要,因此从这些端点复制的密钥构建代码在此处将返回 400。

如何生成密钥 ​

从您的 API 密钥派生它。这使得该值对您的账户是唯一的,在重试时可重现,并且任何其他人都无法推导得出:

python
import hashlib
import hmac

def make_idempotency_key(api_key: str, address: str, amount: int, nonce: str) -> str:
    message = f"{address}:{amount}:{nonce}"
    return hmac.new(api_key.encode(), message.encode(), hashlib.sha256).hexdigest()

**nonce 属于订单,而非请求。**在您端创建订单时仅选取一次,并在每次发送该订单时传递相同的该值 —— 首次尝试和每次重试皆是如此。在发送函数内部生成新值(每次调用时执行 str(uuid.uuid4()))会使每次尝试具有不同的密钥,因此超时后的重试会被当作第二个订单接受并再次扣费。最简单正确的选择是您已有的订单 ID:它在首次尝试前即已存在,且在您的进程重启后依然保留。

python
# 当订单在您的系统中出现时执行一次
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)

# 首次尝试和每次重试时 —— 相同的三个输入,相同的密钥
key = make_idempotency_key(API_KEY, order.address, order.amount, order.id)

headers = {
    "Content-Type": "application/json",
    "X-API-KEY": API_KEY,
    "X-Idempotency-Key": key,
}

密钥有效期为 24 小时。此后相同的 nonce 再次空闲并开启新订单。

请勿使用任何其他人都可以推导得出的值 —— 例如 64 个零、固定单词的摘要。所有账户共享同一密钥空间。此类冲突绝不会暴露其他账户的订单,但您的请求将被拒绝并返回 409,直到其密钥过期为止,这并不是您在重试过程中希望得到的应答。

提交两个相同的订单 ​

有时您确实希望提交两个相同的订单 —— 先后向同一地址发送相同数量的能量。自动密钥无法将其与重试区分开来:两个请求逐字节完全相同,区分它们的唯一依据是它们到达的时刻。

如果没有您自己的密钥,结果取决于它们之间的时间间隔:

两次请求之间的间隔会发生什么
在同一 1 秒窗口内第二个请求被视为重复。它不会被执行:您将收到 208 以及首个订单的响应,包括 orderId。不会对其进行任何扣费
间隔超过一秒两个不同的密钥 —— 两个订单均被创建且均被扣费

因此,如果您依赖自动密钥,请在两个相同的订单之间留出超过一秒的间隔,并读取状态码:208 意味着您刚刚发送的订单未被创建。

暂停等待只是一种变通方案,而非彻底的解决方案。它会隔离每个请求,包括那些您从未打算重复的请求 —— 超时后的重试、连击、队列重新投递的消息。这些也会晚于窗口到达,因此它们会被作为单独的订单创建并单独扣费。此端点的响应超时时间为 10 秒,已经远远超出该窗口:自动密钥无法保护超时后的重试。

您自己的密钥消除了这种不确定性,因为决定权转移到了唯一知晓答案的一方:

您的操作您发送的内容结果
第二个真正的全新订单新的 nonce新密钥 —— 订单被创建
重试未知结果的订单首次尝试的 nonce相同密钥 —— 208,原始响应,无二次扣费

第二行是该请求头存在的原因,也是实现中最容易出错的地方:参见如何生成密钥下的说明。

重复请求的 HTTP 状态码 ​

状态码名称Description
200OK订单处理成功(首次请求)
208Already Reported订单已处理,返回缓存响应
409Conflict请求正在处理中,请勿重试

重复请求 - 已处理 (208) ​

当收到已完成订单的重复请求时:

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.54 TRX deducted",
        "data": {
            "hash": "9e4c20e21e01e4c39b21b670d1ea1fc1e4b0de94d8fbd4c190d5378ba911dfae",
            "energy": 65050,
            "orderId": "1H70bcc7962a",
            "paidTRX": 2.535,
            "delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq"
        }
    },
    "idempotency": {
        "status": "completed",
        "cached": true,
        "original_created_at": "2025-12-03T10:34:49.104896"
    }
}

响应体与原始成功响应完全相同,并附带一个额外的 idempotency 对象,表明这是缓存响应。

重复请求 - 仍在处理中 (409) ​

当原始请求仍在处理中而收到重复请求时:

json
{
    "success": false,
    "error": "duplicate_request_processing",
    "message": "This request is currently being processed. Please wait and do not retry.",
    "idempotency_key": "b9e67b2412d33c92a4f0e1c3d5b7a9f2e4c6d8b0a2f4e6c8d0b2a4f6e8c0d2b4",
    "retry_after_seconds": 3
}

**建议:**在检查订单状态前,等待指定的 retry_after_seconds 秒。

最佳实践 ​

  • 请勿使用相同参数发送并发请求 - 等待每次响应
  • 为每个新订单使用新的 nonce,并对其每次重试使用首次尝试的 nonce
  • 绝不要在发送时重新构建 nonce — 重试必须复现首次尝试的密钥,而不是生成新密钥
  • 通过等待处理 409 响应,而不是立即重试
  • 检查 idempotency.cached 字段以识别缓存响应 — 208 意味着您刚刚发送的订单未被创建

后付费账户 ​

采用后付费结算的账户使用与其他账户相同的端点、URL、请求头和请求体。区别在于订单的支付方式:

  • 不会从您的押金中扣除任何费用。每个成功的订单都将计入您账户在合同约定结算货币下的应付余额。您根据协议按发票进行支付。
  • 您的账户拥有授信额度。只要应付金额在额度范围内,即使押金为零也会接受订单。
  • 仅对已交付的服务进行计费。被拒绝或未执行的订单不收取任何费用。
  • 如果接收地址需要激活,激活是同一订单的一部分,并作为单独费用计入账单。

Netts 可根据申请为账户开启后付费结算。每个响应都会告知您订单的支付方式:paymentMode 为 postpaid 或 prepaid。

额外请求字段 ​

ParameterTypeRequiredDescription
testboolean否true — 仅计算价格。不进行任何下单、交付或扣费
freezePriceboolean否true — 在您的合同下锁定价格 60 秒。不进行任何下单或扣费
quoteIdstring否按照 freezePrice 签发的报价单价格进行下单
priceCurrencystring否TRX(默认)或您合同的结算货币,同 settlement.asset。对于后付费账户,始终包含以您的合同货币计价的金额

quoteId 不能与 test 或 freezePrice 结合使用。请求体中的任何其他字段都将被拒绝。

价格查询 (test: true) ​

json
{
    "amount": 65000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "test": true
}
json
{
    "detail": {
        "code": 10010,
        "msg": "Test calculation",
        "data": {
            "amount": 65000,
            "unitPriceSun": "20",
            "discount": null,
            "energyTRX": "1.300000",
            "activationTRX": "1.100000",
            "wouldCostTRX": "2.400000",
            "paidTRX": 0,
            "paymentMode": "postpaid",
            "activationCheck": "inactive",
            "alt": {"USDC": {"energy": "0.430541", "activation": "0.364304", "total": "0.794845"}},
            "fxAt": "2026-10-19T07:15:18.469870+00:00"
        }
    }
}
字段Description
unitPriceSun每单位能量以 SUN 计价的价格,包含您的个人折扣(若有)
discount您的个人折扣(type, value)或 null
energyTRX / activationTRX / wouldCostTRX能量费、激活费(如果地址需要)和总计,以 TRX 计价
activationCheckinactive — 地址将被激活并计费;active — 无需激活;unknown — 当前无法检查
alt.<currency>以您的合同货币计价的相同金额
fxAt合同货币金额所采用的汇率时间

固定价格报价 (freezePrice: true) ​

在下单前使用报价锁定您合同下的价格。

  1. 发送带有 "freezePrice": true 的订单请求。响应代码为 10011(Quote issued),包含与价格查询相同的字段,外加 quoteId 和 expiresAt。
  2. 在 60 秒 内发送带有 "quoteId": "<quoteId>" 以及相同的 amount 和 receiveAddress 的订单。
  3. 订单按报价单价格(即报价时的合同价格)进行结算,即使中间价格发生变动。

报价仅可使用一次,且仅适用于同一产品:1 小时报价不可用于支付 5 分钟订单。过期或已使用的报价将被拒绝,且不会创建任何订单。

json
{
    "amount": 65000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "quoteId": "q_4f540f16a2c94b7f8e3d1a6b5c0e9d72"
}

成功订单 ​

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 1.30 TRX for energy + 1.10 TRX for address activation, postpaid",
        "data": {
            "orderId": "1Hf9544a1508",
            "paidTRX": 2.4,
            "hash": "032bda8fa6911b42c15a6d8d30520dc22bcc4077972a1503b6a3fae491967eb4",
            "delegateAddress": "TVnkj2jHKgmea8DVJFo2teD7rRSpH51bne",
            "energy": 65000,
            "activationHash": "259e1ab276114ae717a6f62d7d25eb1f89a2dccb637cbe41be626df3c2a78519",
            "paymentMode": "postpaid",
            "energyTRX": "1.300000",
            "activationTRX": "1.100000",
            "totalTRX": "2.400000"
        }
    }
}
字段Description
paidTRX服务的 TRX 成本。对于后付费账户,不会从押金中扣除
paymentModepostpaid
energyTRX / activationTRX / totalTRX精确金额,保留 6 位小数
quoteId, alt当订单使用报价下单时出现:报价 ID 及报价金额
activationFinal仅当激活金额为预估值时存在且为 false;最终金额将显示在您的发票上

所有其他字段与预付费订单相同。

达到授信额度 (402) ​

json
{
    "detail": {
        "code": 1004,
        "msg": "Postpaid credit limit reached.",
        "paymentMode": "postpaid",
        "reason": "limit_reached"
    }
}

订单未被执行,不计收任何费用。一旦您的付款登记入账或额度上调,将重新接受新订单。

后付费错误代码 ​

代码HTTPDescription
10010200价格查询结果(test)
10011200报价已签发(freezePrice)
1004402达到后付费授信额度
4100400无效请求
4101400不支持的 priceCurrency
4102400quoteId 与 test 或 freezePrice 同时使用
4103409报价已被使用
4104409报价已过期
4105409幂等性密钥已用于其他请求
4106404未找到报价
4107409订单参数与报价不一致
4108400无效的 quoteId 格式
4109422不适用于子账户
5032503价格暂时不可用
5033503汇率暂时不可用
5034503计费服务暂时不可用 — 订单未被接受
5036503授信检查暂时不可用 — 请稍后重试

对于上述所有 4xx 和 503 响应,不进行任何下单且不收取任何费用。

注意事项 ​

  • 订单成功后立即交付能量(通常在 0.5-10 秒内)
  • API 响应超时时间:最长 10 秒,通常在 2 秒内响应
  • 地址激活:如果接收地址未激活,Netts 将按成本价予以激活
  • 激活延迟:对于未激活的地址,由于激活处理过程,API 响应可能需要长达 6 秒
  • 全天候 24/7 处理订单,支持供应商自动故障转移
  • 最低能量数量:61,000 单位
  • 最高能量数量:每笔订单 3,000,000 单位
  • 能量缓冲:自动增加 +50 单位用于供应商补偿(免费提供)
  • 交易哈希:该字段始终存在,但若供应商未立即返回,则可能为空。如需获取哈希,请在下单后不早于 1 分钟 调用 /apiv2/order_check
  • 供应商选择:根据成本和可用性自动选择
  • 订单 ID 格式:1H{request_id},用于统一追踪
  • 定价:根据一天中的时间和能量数量动态调整
  • 时长:固定 1 小时(3600 秒)
  • 速率限制:每个 IP 地址每秒 50 次请求