跳转到主要内容

Webhook

每个账户只有一个 Webhook URL,所有事件都发送到该地址。可在 Dashboard → API 中设置,或使用配置 Webhook。

事件

目前共有六个事件。
order.updated 仅针对使用 API 密钥创建的订单发送。在网站或 Telegram 机器人上完成的购买不会产生 Webhook,即便同一账户仍能正常收到 Smart Mode 事件。

消息信封

每次投递都包含相同的三个顶层字段。timestamp 是我们生成该事件的时刻,ISO-8601,UTC 时区。
Response
请求头:

order.updated

number
订单 ID。
string
energy 或 bandwidth。
string
processing、filled、partial、failed、reclaimed 或 reclaim_failed。该字段是判断依据,请看下面的警告。
string
资源被委托到的地址。
number
下单数量——能量单位或带宽点数。
number
与 volume 相同。之所以保留,是为了无需分辨字段含义即可比较「应交付」与「已交付」。
number
目前实际已委托的数量。订单为 filled 时等于 volume;processing 与 partial 时为已交付分片之和;失败时为 0。
string
订单价格,以 TRX 计,十进制字符串。
string | null
委托该资源的交易。
string | null
租期结束后收回该资源的交易。
string | null
计划收回资源的时间,ISO-8601;不按计时器收回的订单为 null。
Response
请以 status 判断结果,而不是看有没有 delegate_txid。 失败的订单同样可能带有交易 ID——我们特意保留它以便排查故障。您是否拿到资源,只有 status 说了算。
大额订单在内部会被拆分成多笔,但那是我们的事:您每个订单只收到一个 Webhook,而不是每个分片一个。

subscription.transfer

number
该转账所属的 Smart Mode 订阅。
string
发出转账的受监控地址。
string | null
您为该订阅设置的标签。
string
链上的转账交易。
number
本次委托覆盖了多少笔转账。
number
为此委托的能量。
string
为能量扣除的金额,以 TRX 计。
string | null
额外扣除的带宽费用;未扣除时为 null。
string
扣费后的账户余额。
string
转账的处理时间。请注意它位于 data 内部,与信封自身的 timestamp 不同。
Response

Transfer Package 事件

四个 package.* 事件发送给拥有该套餐的账户。未登录、也未使用 API 密钥而通过账单购买的套餐没有所有者,不会产生事件。已取消的账单、被拒绝的购买以及处于人工审核中的购买也不会产生事件;审核中的套餐在激活时发送 package.activated。 每个 package.* 事件的 data 中都包含以下字段:
number
套餐 ID——即套餐列表中的 id。
string
套餐服务的地址。
string
事件发生后的套餐状态:package.transfer 为 active 或 completed,package.completed 为 completed,package.activated 为 active,package.expired 为 expired。
number
购买套餐时包含的转账次数。
number
事件所报告的变化之后该套餐剩余的转账次数——是绝对值,而不是差值。
事件可能乱序到达。每个事件单独投递,并在约 35 秒内重试,因此由某笔转账引起的 package.completed 可能早于该转账的 package.transfer 到达,package.transfer 也可能早于 package.activated 到达。对每个 package_id,请保留您见过的最小 remaining:它永远不会增加。completed 和 expired 是最终状态。
remaining 也可能在没有事件的情况下减少。多次转账套餐每天扣除一次转账作为每日订阅——第一次在激活时扣除,因此 500 次转账的套餐从 remaining: 499 开始——这笔扣除不会单独通知。同一地址在同一区块中的两笔转账可能报告相同的 remaining。请把 remaining 当作参考,把套餐列表当作准确来源。
识别重发时,package.transfer 请使用 (package_id, tx_hash),其他事件使用 (event, package_id):重发的请求体、timestamp 和签名都相同。

package.transfer

该地址的一笔转账已由套餐支付。转账计入的每个套餐各发送一次——几乎总是每笔转账一个事件;如果一笔转账用完了一个套餐的最后一次转账并继续使用下一个套餐,则每个套餐各发送一个事件。
string
链上的转账交易。
number
本次交易从该套餐扣除的转账次数。向不持有 USDT 的地址转账需要双倍能量,计为 2,这两次可能分摊到两个套餐。
此处如果这笔转账用完了套餐,status 为 completed。
Response

package.completed

套餐已停止为转账服务。
string
transfer——一笔转账用完了套餐;subscription——每日扣除用完了套餐;manual——客服关闭了套餐。manual 时 remaining 可能大于零,但这些转账已无法使用。
string | null
当 reason: "transfer" 时,为关闭套餐的那笔转账;否则为 null。
没有剩余的套餐——例如一个普通的单次转账套餐,其首次每日扣除已用掉唯一的一次转账——会被下一笔转账关闭,而不会有自己的 package.transfer:您只会收到带有该转账 tx_hash 的 package.completed。
Response

package.activated

套餐已激活,从现在起其转账会获得能量。每次激活都会发送——包括余额购买(其响应已显示 active)和账单支付(在链上看到付款后不久激活套餐)。
string
套餐的支付方式:精确为 balance、TRX 或 USDT。
Response

package.expired

套餐账单未在 30 分钟内支付。未扣任何费用;如需新账单,请重新购买。没有额外字段;remaining 等于 quota_total,且不可使用。
Response

投递

  • 最多 3 次尝试,两次之间分别间隔 1 秒和 4 秒。成功之后以及最后一次尝试之后没有停顿。
  • 每次尝试超时 10 秒。
  • 我们接受任何 2xx。其他一律视为失败尝试。
  • 不跟随重定向。 301/302 是一次失败尝试,而不是跳转。
  • 错过的事件不会补发。三次尝试都失败,该事件就丢失了;请用查询订单或套餐列表对账,而不是等待重发。
您的 URL 必须解析到公网地址。回环、私有和链路本地地址段会被拒绝,无法解析的主机同样如此——这两种情况下都不会发送任何请求,也不会写入日志。

验证签名

每个请求都带有 X-Webhook-Signature: sha256=<hex>,即以您的 Webhook 密钥对原始请求体计算的 HMAC-SHA256。 两个细节决定您的校验能否成功:
  1. 比较前请去掉 sha256= 前缀。该请求头不是纯十六进制摘要。
  2. 对收到的原始字节做哈希,而不是对重新序列化后的对象。解析 JSON 再重新输出会改变键的顺序和空格,签名永远对不上。
签名密钥显示在 Dashboard → API 中 Webhook URL 旁边。它不会返回给使用 API 密钥的请求——要查看必须在网站上登录。
在依据内容采取行动之前先验证签名,并使用恒定时间比较(hmac.compare_digest / crypto.timingSafeEqual)。用 == 比较会通过时间泄露信息。