Files
tripocli/TRIPO_API_SPEC.md
T
Mrpzx 977f97995a tripocli v2.0.0:Tripo AI 3D 生成与加工 CLI(面向 Agent 与开发者,纯 Python 标准库、零第三方依赖)
覆盖文生 3D、图生 3D、多视图、批量生成,以及重拓扑、绑定、动画、智能分割、
纹理、PBR、智能 UV、部件补全、格式导出与下载。

代码组织:一个功能一个模块(tripo/features/),入口薄壳 tripocli.py。
2026-10-13 19:22:54 +08:00

281 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tripo API 规范(实测契约)
本文档记录 `tripocli` 在真实生产环境(studio.tripo3d.ai / api.tripo3d.ai)**实测验证过**的接口契约,
供接入方与其它 Agent 参考。带 ⚠️ 的都是踩过的坑,按实测结果书写,不是推测。
---
## 一、鉴权
### 1. 请求头(业务接口必带)
```http
Accept: application/json
Content-Type: application/json
Origin: https://studio.tripo3d.ai
Referer: https://studio.tripo3d.ai/
Authorization: Bearer <JWT>
x-tripo-device-id: <device_id>
```
⚠️ **缺少 `Origin`/`Referer` 会返回 `403 code=1017 Access denied: invalid domain`**(实测)。
### 2. Cookie 换 JWT
```
GET /v2/studio/studio/whoami?tokenizeAs=default_jwt
```
- 鉴权:**必须用 Cookie**(`ory_kratos_session`)。⚠️ 实测**用 Bearer JWT 调这个接口会 401**。
- 响应关键字段:`tokenized`(即后续使用的 JWT,**有效期约 15 分钟**)、`expires_at`(会话到期)、`id`、`identity.traits.email`。
- Cookie `ory_kratos_session` 有效期约 **30 天**。
- ⚠️ 短时间内高频调用该接口偶发瞬时 `401`,需重试。
---
## 二、账户
| 功能 | 方法与路径 | 说明 |
|---|---|---|
| 积分/会员 | `GET /v2/studio/user/profile/payment` | `data.wallet.total_credit`、`expiring_credit`、`expiring_date`;`data.member.type`、`valid_until` |
| 试用额度 | `POST /v2/studio/operation/quota`(body `{}`) | `data.quota.generation.*`、`data.quota.uv_edit.*` |
| 资产列表 | `GET /v2/studio/assets/v2` | ⚠️ 需要 `asset_type=mine`(实测 `model`/`personal`/`team` 等都报 `invalid asset type`)+ `type=model` |
---
## 三、生成接口
三者返回结构一致:`data.{task_id, project_id, operator_id, is_nsfw}`。
### 1. 文生 3D
```
POST /v2/studio/operation/text_to_model
```
| 字段 | 类型 | 说明 |
|---|---|---|
| `prompt` | string | 必填 |
| `model_version` | string | 高精度 `v3.1-20260211` / `v3.0-20250812` / `v2.5-20250123`;智能网格 `Nexus-v2.0-20260801`(P2.0,实测可用)/ `Nexus-v1.0-20260214` |
| `face_limit` | int | 高精度默认 2000000;智能网格常用 25000 |
| `quad` | bool | 智能网格一般 true |
| `texture` / `pbr` / `delight` | bool | 默认 true |
| `texture_quality` | string | `standard` / `detailed` |
| `texture_alignment` | string | `original_image` |
| `geometry_quality` | string | `detailed` |
| `smart_poly` | bool | 智能网格模式 true |
| `t_pose` | bool | 人形角色 T-Pose |
| `visibility` | string | `shareable` / `private` |
| `model_count` | int | 1 / 2 / 4(⚠️ 多候选时 `project.model_url` 只给一个) |
### 2. 图生 3D(⚠️ 必须带审核结果)
```
POST /v2/studio/storage/temporary_token # body: {"client":"aws","format":"png|jpg|webp"}
→ sts_ak / sts_sk / session_token / host / resource_bucket / resource_uri
PUT https://{bucket}.{host}/{resource_uri} # AWS SigV4 直传(region us-west-2)
POST /v2/studio/audit/image # body: {"image": {"bucket","key"}} → {"data":{"result":"pass"}}
POST /v2/studio/operation/image_to_model
```
`image` 对象**必须**包含审核结果与来源,否则一律返回 `11002 Image audit result not found`:
```json
{
"image": {
"bucket": "tripo-data",
"key": "tripo-studio/<date>/<uuid>/input.webp",
"image_audit_result": "pass",
"image_source": "upload"
},
"model_version": "v3.1-20260211",
"face_limit": 2000000,
"quad": false,
"texture": true,
"pbr": true,
"delight": true,
"texture_alignment": "original_image",
"texture_quality": "detailed",
"geometry_quality": "detailed",
"smart_poly": false,
"visibility": "shareable"
}
```
### 3. 多视角图生 3D
```
POST /v2/studio/operation/multiview_to_model
```
⚠️ `image` 必须是**恰好 4 个**已审核图片对象的数组(前/左/右/后);少于 4 个返回 `1004 Invalid parameter(s)`,未审核返回 `11002`。
### 4. 导入自己的模型(上传 glb/obj/fbx/stl)
```
POST /v2/studio/storage/temporary_token # body: {"client":"aws","format":"glb|obj|fbx|stl"}
PUT https://{bucket}.{host}/{resource_uri} # AWS SigV4 直传(同图片)
POST /v2/studio/operation/import_user_model
```
⚠️ body 是**嵌套**的,`model` 里放 S3 对象(实测):
```json
{
"format": "glb",
"model": {"bucket": "tripo-data", "key": "tripo-studio/<date>/<uuid>/input.glb"},
"name": "my_model.glb",
"transform_matrix": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1],
"use_original_uv": true
}
```
→ `data.{project_id, operator_id}`(随后可用 progress 轮询;实测导入成功后可下载)。
⚠️ **`transform_matrix`** 是 4x4 矩阵(前端在导入对话框里让用户转模型用的「找到最佳角度」),CLI 用单位矩阵即可。
⚠️ 导入会**丢弃自定义材质与多层节点层级**(界面明确提示);个别模型(如 Tripo 自己导出的带材质 glb)服务端处理会失败(`9104` / `Internal algorithm error`),换标准 obj/glb 即可。
### 5. 部件名(`part_name_list`)来自模型文件,不在接口里
`remesh` / `pbr` / `texture_model` 的 `part_name_list` 取的是**模型里的节点名**:
未拆分为单个 `tripo_node_<operator_id>`,智能分割后为每个部件一个 `tripo_part_<n>`。
⚠️ 项目详情接口**不返回**部件名,前端是**下载 GLB 后解析 `nodes[].name`** 得到的;
`tripocli` 用同样办法(纯标准库解析 GLB 的 JSON chunk),读不到时回退到 `tripo_node_<operator_id>`。
### 6. 批量图生 3D
```
POST /v2/studio/operation/batch_image_to_model
```
⚠️ 字段名是 **`image`**(数组,不是 `images`,写错返回 `type mismatch for field "image"`);响应 `data` 是**数组**,每项 `{project_id, operator_id}`。
---
## 四、任务与项目
| 功能 | 方法与路径 |
|---|---|
| 进度轮询 | `POST /v2/studio/progress`,body `{"ids":["<operator_id>"]}` → `[{status, progress, left_time, point_cloud_model_url}]`,`status ∈ running/success/failed` |
| 项目详情 | `GET /v2/studio/project/detail/v3/<project_id>?locale=zh-CN` → `data.model_url`、`cover_image`、`operator.{operator_id, status, model_version, is_textured, ...}` |
⚠️ 轮询偶发裸 `502`,需重试而非中断。
---
## 四、文生图(参考图生成)
```
POST /v2/studio/image/gen_image_v2
{
"if_upload": true, "sketch_to_render": false, "t_pose": false,
"amount": 4, // 1-4
"model_version": "gemini_3.1_flash_image_preview",
"prompt": "a cute cartoon wooden barrel",
"resolution": "1K", // 实测 1K/2K/4K 有效,8K 报 400
"scale": "1:1" // 1:1 16:9 9:16 4:3 3:4
}
→ {"task_id": ..., "asset_id": ..., "remaining_free_count": 96}
POST /v2/studio/image/get_image_asset {"asset_id": "..."}
→ {status, type:"generate_image", output:{data:[{bucket,key,url}]}}
```
图片模型 `model_version`(在页面逐个选中并抓包确认):
| 界面名 | model_version |
|---|---|
| Nano Banana 2(默认) | `gemini_3.1_flash_image_preview` |
| Nano Banana Pro | `gemini_3_pro_image_preview` |
| GPT Image 2 | `gpt_image_2` |
| GPT Image 2.5 | `gpt_image_2.5_sunburst` |
| Midjourney v8.2 | `midjourney` |
> 异步:先 `gen_image_v2` 拿 `asset_id`,再轮询 `get_image_asset` 直到 `status=success`。
### 图片侧其它接口(实测)
| 功能 | 方法与路径 | 说明 |
|---|---|---|
| 模板清单 | `GET /v2/studio/image/available_templates` | 返回 `{templates:[{template_id,title,description,category,secondary_tag,tag}]}`。**模板是客户端的提示词+参数预设**,请求体里没有 `template_id`(实测),CLI 只用来列清单 |
| 单图→多视角图 | `POST /v2/studio/image/gen_multiview` | body `{image, model_version, amount, resolution, scale}`(`image` 需先上传+审核)。结果 `get_image_asset` 的 `type="multiview_images"`,`output.data` 为 4 张(实测出图 4 张) |
| 图片资产 | `POST /v2/studio/image/image_assets` | body `{page_num,page_size}` |
| 图片放大 | `POST /v2/studio/image/upscale` | 需 `asset_id`(实测:只给 image 报 `field "asset_id" is not set`) |
| 图片拆分 | `POST /v2/studio/image/split` | — |
| 重新生成 | `POST /v2/studio/image/re_gen_image` / `re_gen_multiview` | — |
| 批量删除 | `POST /v2/studio/image/batch_delete` | — |
---
## 五、后处理算子
⚠️ **通用规则**:每个算子都会为项目新建一个 operator;**必须等上一个算子 `success` 之后**才能对同一项目再提交,
否则返回 `2021 the status of task is not success`。
⚠️ **`part_name_list`**:`remesh` / `pbr_generate` / `texture_model` 都需要它,值为
`["tripo_node_<项目当前 operator_id>"]`。缺它时请求会被接受,但任务在 **100% 处失败**(实测)。
| 功能 | 路径 | 关键字段 |
|---|---|---|
| 重拓扑 | `POST /v2/studio/operation/remesh` | `bake:true`、`face_limit`、`quad`、`smart_poly:false`、`model_version:"default"`、`part_name_list` |
| 绑定前检查 | `POST /v2/studio/operation/pre_rig_check` | `project_id`(`model_version` 可选)→ `{check_success, riggable, rig_type}` |
| 骨骼绑定 | `POST /v2/studio/operation/rigging_model` | `project_id`、`rig_type:"biped"`、`spec`、`model_version`。⚠️ **spec 有 5 个值**(取自前端数据表 + 实测核对):`mixamo` / `actorcore`(界面对应 ActorCore)/ `unreal`(UE5 Mannequin)/ `unity`(Unity Humanoid Compatible)/ `vrm`(VRM 1.0 Humanoid) |
| 动画重定向 | `POST /v2/studio/operation/retarget_model` | ⚠️ 动作用 `animations` **数组**:`["preset:biped:afraid"]`;+ `project_id`、`rig_type:"biped"`、`model_version:"default"`。⚠️ **动画结果不在顶层 `project.model_url`**(那是 `rigging` 算子的带网格绑骨模型),而在 `project.operator.retarget[]` 数组中(按 `operator_id` 匹配取 `model_url`);且该 GLB 仅含 65 根骨骼动画轨道(约 100–500KB,不含 Mesh),在 Three.js / Godot 中需与 `rigging` 本体 SkinnedMesh 配合播放 |
| 3D 风格化 | `POST /v2/studio/operation/stylize` | `project_id`、`model_version`、`style`(实测 `"clay"` 黏土风可用) |
| 取消任务 | `POST /v2/studio/operation/cancel` | `operator_id`、`scene`(仅允许 `"workspace"` 或 `"assets"`)、`operation_type`(20 种枚举:`text_to_model`/`image_to_model`/`multiview_to_model`/`ai_segmentation`/`ai_completion`/`mesh_fill`/`modification`/`skeleton_adjustment`/`texture_generation`/`pre_rig_check`/`rigging`/`retarget`/`stylize`/`export`/`retexture`/`apply_texture`/`pbr`/`remesh`/`texture_upscaler`/`image_edit_to_model`) |
| 重命名项目 | `POST /v2/studio/operation/update_name` | `project_id`、`name`(成功返回 `null`) |
| 图文生 3D(已废弃) | `POST /v2/studio/operation/image-prompt-model` | ⚠️ 服务端已下线,固定返回 `code=2040 This endpoint is no longer accepting requests` |
| 智能分割 | `POST /v2/studio/operation/ai_segmentation` | ⚠️ `model_version` 用**分割模型自己的版本** `v2.0-20260430`(传项目版本会 `1001`);`segmentation_granularity:"balanced"`(界面「标准」;粗略/精细取值未确认) |
| 纹理生成 | `POST /v2/studio/operation/texture_model` | `texture_quality`、`texture_alignment`、`part_name_list`(⚠️ 已贴图模型会失败) |
| 重贴图(魔法笔刷) | `POST /v2/studio/operation/retexture_generate` / `apply_retexture` / `get_retexture` / `get_retexture_images` | ⚠️ **纯交互式**:body 需在 3D 画布上涂抹出的遮罩快照(`snapshot()` → `matrix` + 涂抹区域)+ `magicBrushPrompt:{text,weight}`,且要求模型**已贴图**、未分割、未超清。CLI 未封装 |
| 纹理放大 | `POST /v2/studio/operation/texture_upscaler` | ⚠️ 字段是 `texture_quality:"detailed"`(不是 `texture_resolution`,写错会 `1001`);+ `model_version` |
| PBR | `POST /v2/studio/operation/pbr_generate` | `project_id`、`model_version`、`part_name_list` |
| 智能 UV | 见下方三步 | 上下文驱动 |
| 部件补全 | `POST /v2/studio/operation/mesh_fill` / `ai_completion` | `part_names`(数组)、`model_version`。部件名 = 模型 GLB 的节点名(`tripo_part_<n>`),实测可用 |
| 网格编辑 | `POST /v2/studio/operation/local_edit` | `project_id`、`source_operator_id`、`bbox:[[min],[max]]`(归一化 -1..1)、`face_limit`。⚠️ 仅**智能网格(Nexus)** 且未贴图/未绑定/未分割/未 PBR 的模型可用(界面据此隐藏「编辑」页) |
### 智能 UV(三步,实测)
```
POST /v2/studio/operation/uv_edit/generate
{project_id, current_operator_id, action:"generate"} → 生成 UV 候选(新 operator)
POST /v2/studio/operation/uv_edit/apply
{project_id, current_operator_id, candidate_operator_id} → 保存/应用候选
POST /v2/studio/operation/uv_edit/context
{project_id, current_operator_id} → 查询当前处于哪一步
```
⚠️ 只 `generate` 不 `apply`,上下文会停在「待保存」,再调 `generate` 报
`2046 UV Edit action no longer matches the context`。另外要求网格为低模(约 ≤8 万三角面)。
> 说明:`ai_segmentation` / `texture_upscaler` 等对**不同模型**可能服务端失败,属模型相关行为,与请求字段无关。
### 动作预设清单(无接口,来自前端静态表)
服务端**没有**提供预设目录接口,实测:
- `POST /v2/studio/motion/list_assets`(body `{}`)→ 返回的是**用户自己的动画资产**(`{active_tasks, assets}`),不是预设目录;
- `POST /v2/studio/operation/get_user_operation_context` `{"record_type":"recent_retarget_motions"}`
→ 只返回**最近用过**的:`{preset:[...], generated:[...]}`。
完整目录在 studio 前端 chunk(`BLST4mg6.js`)的静态表里,已提取到 `tripo/data/motions.json`:
- 格式 `preset:<rig_type>:<name>`,`rig_type ∈ {biped, aquatic, quadruped, hexapod, octopod, serpentine}`
- **biped 97 个**,其余体型各 1 个(`walk`/`march`)
- 预览图:`https://tripo-public.tripo3d.ai/studio_riging_data/<rig_type>/<name>.avif`
用 `tripocli animate --list` 查看全部。
### 文字生成动作(AI 动画,实测三段式)
```
1) POST /v2/studio/motion/generate
{"segments": [{"duration_seconds": 5, "prompt": "让角色挥手打招呼"}]}
→ {task_id, status:"queued"}
(segments 是数组 → 支持多阶段动作)
2) POST /v2/studio/motion/get_task {"task_id": "..."}
→ 轮询直到 status="success",取 asset_id(即 motion_asset_id)
3) POST /v2/studio/operation/retarget_model
{"motion_asset_id": "<asset_id>", "model_version":"default",
"project_id": "...", "rig_type": "biped"} → 把动作套到模型上
```
其它已验证接口:`POST /v2/studio/motion/list_assets`(我的动作资产)、`/motion/get_asset`、
`/motion/list_active_tasks`(正在跑的任务)。
---
## 六、导出与下载
```
POST /v2/studio/operation/export
body: {project_id, operator_id, format:"fbx|gltf|obj|stl|usdz|3mf", name, model_version}
→ data.{operator_id, operation_id} # 异步,用 progress 轮询
POST /v2/studio/operation/download_with_name
body: {operator_id, file_name}
→ data.model_url # 带 Content-Disposition 的签名直链
```