http
Base URL: https://openapi.tripo3d.ai/v3
Endpoint: POST https://<your-endpoint>
当任务完成或失败、或积分余额低于你在账单中的告警阈值时,Tripo 会向你的 HTTPS URL 投递 JSON,因此无需轮询
GET /v3/tasks/{task_id}。配置流程
- 打开 设置 → Webhooks,点击 添加端点。
- 填写 HTTPS 回调地址(例如
https://api.yourapp.com/tripo-webhook)。 - 选择要订阅的事件类型。
- 点击 保存端点。
- 复制 签名密钥(
whsec_…)——仅显示一次,请像 API Key 一样妥善保管。
事件类型
task.completed:任务成功结束。task.failed:任务失败或已取消。balance.low:余额低于在 账单 → 额度告警中设定的阈值(告警本身不决定任务是否成功)。
重试策略
若你的端点返回非 2xx 或超时,Tripo 会自动重试。可在 设置 → Webhooks → 最近投递记录 中排查失败原因。最佳实践
- 处理业务前务必用签名密钥验证载荷来源。
- 约 5 秒内返回
2xx;重逻辑异步处理。 - 使用
Tripo-Webhook-Delivery做投递去重。 - 在 账单 中开启
balance.low以便余额不足前收到通知。
请求参数
请求体
idstring必选
组合后的事件 ID(通常包含 task_id 与事件类型)。
typestring必选
取值为
task.completed、task.failed、balance.low 之一。created_atstring必选
事件创建时间,ISO 8601 字符串。
dataobject必选
事件相关载荷。任务类事件中的字段与任务查询接口返回一致;balance.low 时包含与余额相关的字段。
说明
- 任务事件:通常包含
task_id、type、status,成功时含output。 balance.low:阈值在 账单 → 额度告警 中配置。
Tripo-Webhook-Idheader · string必选
Tripo 侧 Webhook 端点 ID。
Tripo-Webhook-Deliveryheader · string必选
唯一投递 ID——若同一逻辑事件多次投递,可据此去重。
Tripo-Webhook-Eventheader · string必选
与 JSON 体中的 type 一致。
Tripo-Webhook-Signatureheader · string必选
使用签名密钥对
{时间戳}.{原始请求体} 做 HMAC-SHA256。格式: t=<unix>,v1=<hex>。说明
- 从请求头解析
t与v1。 - 以密钥计算 HMAC-SHA256(
t + "." + 原始 body),小写十六进制。 - 与
v1做常量时间比较。 - 可选:若 t 与当前时间相差超过约 5 分钟则拒绝(防重放)。
Content-Typeheader · string必选默认值: application/json
固定为 application/json。
返回参数
HTTPstatus必选
应尽快返回 2xx(数秒内)。在重计算完成前即可先响应。
示例
task.completed
{
"id": "task_abc123:task.completed",
"type": "task.completed",
"created_at": "2026-05-06T12:00:00Z",
"data": {
"task_id": "task_abc123",
"type": "text_to_model",
"status": "success",
"output": {
"model_url": "https://cdn.tripo3d.ai/output/model_pbr.glb"}
}
}balance.low
{
"id": "evt_balance_low:balance.low",
"type": "balance.low",
"created_at": "2026-05-06T12:00:00Z",
"data": {
"balance": 1200,
"threshold": 5000
}
}验证 · Python
import hmac
import hashlib
import time
def verify_webhook(payload: bytes, signature_header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in signature_header.split(","))
timestamp = parts.get("t", "")
expected_sig = parts.get("v1", "")
if abs(time.time() - int(timestamp)) > 300:
return False
computed = hmac.new(
secret.encode("utf-8"),
f"{timestamp}.{payload.decode('utf-8')}".encode("utf-8"),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed, expected_sig)验证 · JavaScript
const crypto = require("crypto");
function verifyWebhook(payload, signatureHeader, secret) {
const parts = Object.fromEntries(
signatureHeader.split(",").map(p => p.split("=", 2))
);
const timestamp = parts.t;
const expectedSig = parts.v1;
if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) {
return false;
}
const computed = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${payload}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(expectedSig)
);
}Tripo-Webhook-Signature
Tripo-Webhook-Signature: t=1714992000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8f9task.failed
{
"id": "task_abc123:task.failed",
"type": "task.failed",
"created_at": "2026-05-06T12:00:05Z",
"data": {
"task_id": "task_abc123",
"type": "text_to_model",
"status": "failed",
"error": {
"code": "task_failed",
"message": "Generation failed"}
}
}