Webhook 回调 — API 参考
注册与测试事件推送目标端点。
| 方法 | 路径 | 概览 |
|---|---|---|
GET | /v1/webhooks | 列出推送端点 |
POST | /v1/webhooks | 注册推送端点 |
GET | /v1/webhooks/{webhookId} | 读取单个端点详情 |
PATCH | /v1/webhooks/{webhookId} | 修改端点配置 |
DELETE | /v1/webhooks/{webhookId} | 删除端点 |
POST | /v1/webhooks/{webhookId}/rotate-secret | 轮换生成新的签名密钥 |
POST | /v1/webhooks/{webhookId}/test | 发送测试推送 |
GET | /v1/webhooks/{webhookId}/deliveries | 单个端点的投递记录日志 |
基于 openapi.yaml 在构建时生成。基准 URL 为 https://api.tenergy.me/v1,Nile 测试网环境为 https://api-nile.tenergy.me/v1(详见环境说明)。下述每个请求均遵循身份鉴权规范进行签名,除非鉴权行另有说明。
列出推送端点
GET /v1/webhooks · listWebhooks
鉴权: API 密钥 (HMAC)。
此列表接口绝不返回端点的 secret 签名密钥。
响应
| 状态码 | 含义 |
|---|---|
200 | OK |
401 | 缺少、格式错误或已被拒绝的凭据。 |
500 | 服务端内部错误。 |
响应字段
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
data | array of object (WebhookEndpoint) | 是 | |
data[].id | string | 是 | |
data[].url | string (uri) | 是 | |
data[].role | enum: primary, backup | 是 | |
data[].events | array of enum (13 values, WebhookEventType) | null | null 表示订阅所有类型事件。 | |
data[].is_active | boolean | 是 | |
data[].last_delivery_at | string (date-time) | null | ||
data[].last_delivery_status | integer | null | ||
data[].created_at | string (date-time) | 是 | |
data[].updated_at | string (date-time) | ||
max_endpoints | integer | 是 | |
roles | array of enum: primary, backup |
注册推送端点
POST /v1/webhooks · createWebhook
鉴权: API 密钥 (HMAC)。
返回一个仅展示一次的签名密钥 secret。所有向该端点投递的事件均使用它进行验签 —— 请务必立即妥善保存;若遗失请调用轮换接口,而不要重复注册。
每个账户最多配置两个端点:一个主端点 primary 和一个备用端点 backup。推送机制并非扇出广播(fan-out)—— 所有事件优先投递至主端点,仅当主端点的重试全部耗尽后,才会降级切换至备用端点重试。创建的第一个端点自动作为主端点。
URL 校验规则(在创建和修改时均会执行严格校验):必须为 https;必须解析至公网可路由 IP 地址(本地回环 loopback、RFC 1918 私网网段、链路本地如 169.254.169.254 等不可路由地址均会被拒绝);URL 中禁止包含凭据;最大长度 2048 字符。
完整的事件字典、请求载荷结构、签名校验机制及重试调度策略请参阅 Webhook 回调。
请求体
JSON (WebhookRequest),必填。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
url | string (uri) | 是 | 公网可解析的 HTTPS 地址,不包含认证凭据。 |
role | enum: primary, backup | 省略时自动采用第一个空闲角色。 | |
events | array of enum (13 values, WebhookEventType) | 投递的事件类型列表。省略时表示接收全部事件(推荐做法:新事件类型上线时无需重新配置即可自动接收)。建议在业务逻辑中根据 event 字段分发并忽略未处理的类型。 |
来自规范的请求体示例(示意数值):
{
"url": "https://acme.example/hooks/tenergy",
"role": "primary",
"events": ["order.confirmed","order.failed","balance.credited"]
}
响应
| 状态码 | 含义 |
|---|---|
201 | 创建成功。secret 仅在本次响应中返回。 |
400 | 格式错误的请求 —— 无效 JSON、未知字段或字段类型错误。 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
409 | 请求与当前对象的状态产生冲突。 |
422 | 语法合法但逻辑上无法满足操作要求。 |
500 | 服务端内部错误。 |
响应字段
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
id | string | 是 | |
url | string (uri) | 是 | |
role | enum: primary, backup | 是 | |
events | array of enum (13 values, WebhookEventType) | null | null 表示所有事件。 | |
is_active | boolean | 是 | |
last_delivery_at | string (date-time) | null | ||
last_delivery_status | integer | null | ||
created_at | string (date-time) | 是 | |
updated_at | string (date-time) | ||
secret | string | 是 | 签名私钥。仅展示一次,无法通过 GET 再次获取。 |
读取单个端点详情
GET /v1/webhooks/{webhookId} · getWebhook
鉴权: API 密钥 (HMAC)。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 |
响应
| 状态码 | 含义 |
|---|---|
200 | OK |
401 | 缺少、格式错误或已被拒绝的凭据。 |
404 | 目标对象不存在或属于其他账户。 |
500 | 服务端内部错误。 |
响应字段 (WebhookEndpoint)
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
id | string | 是 | |
url | string (uri) | 是 | |
role | enum: primary, backup | 是 | |
events | array of enum (13 values, WebhookEventType) | null | null 表示所有事件。 | |
is_active | boolean | 是 | |
last_delivery_at | string (date-time) | null | ||
last_delivery_status | integer | null | ||
created_at | string (date-time) | 是 | |
updated_at | string (date-time) |
修改端点配置
PATCH /v1/webhooks/{webhookId} · updateWebhook
鉴权: API 密钥 (HMAC)。
修改 url、events、is_active 和/或 role。向备用端点发送 {"role": "primary"} 将在单次事务中互换两个端点的角色,避免出现没有主端点的真空期。修改后的新 URL 会重新触发安全校验。设置 is_active: false 可暂停投递而不丢失端点配置;暂停主端点不会将备用端点自动升为主端点(如需切换流量请互换角色)。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 |
请求体
JSON (WebhookPatch),必填。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
url | string (uri) | ||
role | enum: primary, backup | ||
events | array of enum (13 values, WebhookEventType) | null | ||
is_active | boolean |
响应
| 状态码 | 含义 |
|---|---|
200 | 已更新 |
400 | 格式错误的请求 —— 无效 JSON、未知字段或字段类型错误。 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
404 | 目标对象不存在或属于其他账户。 |
422 | 语法合法但逻辑上无法满足操作要求。 |
500 | 服务端内部错误。 |
响应字段 (WebhookEndpoint)
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
id | string | 是 | |
url | string (uri) | 是 | |
role | enum: primary, backup | 是 | |
events | array of enum (13 values, WebhookEventType) | null | null 表示所有事件。 | |
is_active | boolean | 是 | |
last_delivery_at | string (date-time) | null | ||
last_delivery_status | integer | null | ||
created_at | string (date-time) | 是 | |
updated_at | string (date-time) |
删除端点
DELETE /v1/webhooks/{webhookId} · deleteWebhook
鉴权: API 密钥 (HMAC)。
硬删除;释放被占用的角色名额。该端点队列中尚未完成投递的历史事件将被丢弃。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 |
响应
| 状态码 | 含义 |
|---|---|
204 | 已删除。无响应体。 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
404 | 目标对象不存在或属于其他账户。 |
500 | 服务端内部错误。 |
轮换生成新的签名密钥
POST /v1/webhooks/{webhookId}/rotate-secret · rotateWebhookSecret
鉴权: API 密钥 (HMAC)。
仅展示一次新生成的签名密钥。它将对随后的所有新投递立即生效,没有重叠过渡窗口:请在调用轮换接口前在您的接收端部署好新密钥,或接受在极短窗口期内重试消息验签失败。每个端点拥有各自独立的密钥 —— 轮换主端点密钥不会影响备用端点。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 |
响应
| 状态码 | 含义 |
|---|---|
200 | 已轮换 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
404 | 目标对象不存在或属于其他账户。 |
500 | 服务端内部错误。 |
响应字段
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
id | string | 是 | |
secret | string | 是 |
发送测试推送
POST /v1/webhooks/{webhookId}/test · testWebhook
鉴权: API 密钥 (HMAC)。
向指定端点发送一条模拟事件并反馈您服务器的实际响应。载荷遵循真实规范签名,并在根层级带有 "test": true 标志,以便接收端忽略非业务事件或在识别该标志时不触发正式业务操作。
测试投递不执行失败重试,也不会记录在投递历史日志中。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 |
请求体
JSON。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
event | enum (13 values, WebhookEventType) | 详见 Webhook 回调。充值事件 balance.credited 还额外附带 asset (TRX|USDT)、usdt_amount、rate、rate_source、spread_bps、txid、sender、block_number 等字段。 |
响应
| 状态码 | 含义 |
|---|---|
200 | 已尝试投递;结果描述了接收端的应答情况。 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
404 | 目标对象不存在或属于其他账户。 |
500 | 服务端内部错误。 |
响应字段
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
delivered | boolean | 是 | 当您的端点返回 2xx 状态码时为 true。 |
event | enum (13 values, WebhookEventType) | 是 | 详见 Webhook 回调 完整目录。 |
delivery_id | string | 是 | |
response_status | integer | null | 您端点返回的 HTTP 状态码;连接失败时为 null。 | |
response_body_excerpt | string | null | 您端点返回的前 512 字节内容,便于排错。 | |
error | string | null | 当 delivered 为 false 时的网络传输层错误描述。 | |
duration_ms | integer |
单个端点的投递记录日志
GET /v1/webhooks/{webhookId}/deliveries · listWebhookDeliveries
鉴权: API 密钥 (HMAC)。
此端点排队处理的每次事件记录(最新在前):事件类型、重试次数、当前状态、您服务器返回的最新 HTTP 状态以及下次重试的时间点。测试推送不会在此列出。需要 webhooks.read 权限或具有 viewer 角色的控制台会话。访问其他账户端点返回 404。
请求参数
| 参数名 | 位置 | 类型 | 必选 | 说明 |
|---|---|---|---|---|
webhookId | path | string | 是 | |
limit | query | integer | ||
cursor | query | string | 上次响应中 next_cursor 返回的不透明游标。 |
响应
| 状态码 | 含义 |
|---|---|
200 | OK |
400 | 格式错误的请求 —— 无效 JSON、未知字段或字段类型错误。 |
401 | 缺少、格式错误或已被拒绝的凭据。 |
403 | 已通过认证,但当前密钥无权执行此操作。 |
404 | 目标对象不存在或属于其他账户。 |
500 | 服务端内部错误。 |
响应字段
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
data | array of object (WebhookDelivery) | 是 | |
data[].id | string | 是 | |
data[].event_id | string | 是 | 事件信封 ID —— 幂等去重键,在重试中保持稳定不变。 |
data[].event | enum (13 values, WebhookEventType) | 是 | 详见 Webhook 回调 完整目录。 |
data[].attempt | integer | 是 | 截止目前已尝试投递的次数。 |
data[].state | enum: pending, delivering, delivered, failed, dead | 是 | failed 将在 next_attempt_at 再次重试;dead 表示重试已耗尽不再投递。 |
data[].response_status | integer | null | 是 | 最近一次尝试返回的 HTTP 状态码;尚未尝试或连接失败时为 null。 |
data[].error | string | null | 是 | 最近一次尝试的网络传输错误。 |
data[].next_attempt_at | string (date-time) | null | 是 | |
data[].delivered_at | string (date-time) | null | 是 | |
data[].created_at | string (date-time) | 是 | |
data[].updated_at | string (date-time) | 是 | |
next_cursor | string | null | 是 |
来自规范的 200 响应示例(示意数值):
{
"data": [
{
"id": "dlv_01K5YA1B2C3D4E5F6G7H8J9K0M",
"event_id": "evt_01K5YA1B2C3D4E5F6G7H8J9K0N",
"event": "order.confirmed",
"attempt": 2,
"state": "failed",
"response_status": 502,
"error": null,
"next_attempt_at": "2026-09-25T10:31:00.000Z",
"delivered_at": null,
"created_at": "2026-09-25T10:30:00.000Z",
"updated_at": "2026-09-25T10:30:30.000Z"
}
],
"next_cursor": null
}