API 参考
Base URL:http://<你的服务器IP或域名>:8080
认证
所有业务接口需在请求头中携带:
| Header | 值 | 必填 |
|---|---|---|
X-API-Key | 你的 API 密钥 | ✅ |
安全提醒
不要把 API Key 写在前端代码中。应放在后端服务或 CI 流水线中使用。
异步任务流程
POST compress → 返回 task_id
GET tasks/{id} → pending / processing / completed / failed
GET download → 下载结果文件| status | 含义 | 操作 |
|---|---|---|
pending | 排队中 | 继续轮询 |
processing | 处理中 | 继续轮询 |
completed | 完成 | 调用 download |
failed | 失败 | 查看 error 字段 |
一、系统状态
GET /api/v1/health
无需认证。
Response 200
{ "status": "ok" }GET /api/v1/capabilities
查询当前服务支持的能力。
Response 200
{
"engines": ["draco", "meshopt"],
"formats": ["glb", "gltf", "obj", "fbx", "stl", "dae", "ply"],
"features": ["compress", "convert", "repair", "diagnose", "texture_optimize", "texture_ktx2"]
}二、模型压缩
POST /api/v1/compress
提交压缩任务。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件(GLB/glTF/OBJ/FBX 等) |
engine | string | ✅ | draco 或 meshopt |
level | integer | ❌ | 压缩级别 1-10,默认 7。数值越大压缩率越高 |
position_quantization_bits | integer | ❌ | 位置精度(仅 Draco),默认 14,范围 8-24 |
normal_quantization_bits | integer | ❌ | 法线精度(仅 Draco),默认 10 |
texcoord_quantization_bits | integer | ❌ | UV 精度(仅 Draco),默认 12 |
color_quantization_bits | integer | ❌ | 颜色精度(仅 Draco),默认 8 |
generic_quantization_bits | integer | ❌ | 通用属性精度(仅 Draco),默认 12 |
meshopt_compression_level | string | ❌ | Meshopt 等级:high / medium / low,默认 high |
Response 200
{
"task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"message": "任务已提交,正在排队"
}三、格式转换
POST /api/v1/convert
将模型从一种格式转换为另一种。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件 |
target_format | string | ✅ | glb / gltf / obj / fbx / stl / dae / ply |
目标为
gltf时输出.zip包(含 .gltf + .bin + 贴图)。
Response 200
{
"task_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"status": "pending"
}四、模型修复
POST /api/v1/repair
自动去空节点、修法线、合并重复顶点、删退化面等。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件 |
Response 200
{
"task_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"status": "pending"
}五、模型诊断
POST /api/v1/diagnose
对模型全面体检,生成详细报告(不修改原文件)。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件 |
Response 200(任务完成后)
诊断结果内嵌在 查询任务 的响应 result 字段中:
{
"result": {
"format": "glb",
"version": "2.0",
"file_size_bytes": 15728640,
"meshes": [{
"name": "Mesh_0",
"vertices": 24568,
"triangles": 48192,
"has_normals": true,
"has_texcoords": true,
"has_colors": false,
"has_tangents": true,
"skinned": false,
"morph_targets": 0,
"issues": [
{ "type": "degenerate_faces", "count": 12, "severity": "low" },
{ "type": "duplicate_vertices", "count": 234, "severity": "medium" }
]
}],
"textures": [
{ "name": "baseColorTexture", "format": "jpeg", "width": 2048, "height": 2048, "size_kb": 512 }
],
"animations": [],
"total_issues": 246,
"recommendations": ["建议运行 repair 修复退化面和重复顶点"]
}
}六、纹理优化
POST /api/v1/textures/optimize
对模型贴图或单独图片进行 JPEG/WebP/PNG 压缩。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件或单独图片 |
format | string | ✅ | jpeg / webp / png |
quality | integer | ❌ | 质量 1-100,默认 82(JPEG/WebP);PNG 压缩级 1-9,默认 6 |
Response 200
{
"task_id": "d4e5f6a7-b8c9-0123-defa-234567890123",
"status": "pending"
}POST /api/v1/textures/ktx2
KTX2(Basis Universal)编码,GPU 直接加载,Web3D 常用。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | File | ✅ | 模型文件或图片(PNG/JPEG) |
uastc | boolean | ❌ | UASTC 高质量模式,默认 false(ETC1S) |
quality | integer | ❌ | ETC1S: 1-255 默认 128;UASTC: 0-4 默认 2 |
Response 200
{
"task_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"status": "pending"
}ETC1S vs UASTC
| ETC1S(默认) | UASTC | |
|---|---|---|
| 压缩率 | 高(~1/10) | 中(~1/4) |
| 视觉质量 | 复杂贴图可能轻微模糊 | 接近原始质量 |
| 适用场景 | 移动端 / 体积敏感 | PC 端 / 高保真 |
七、任务管理
GET /api/v1/tasks/{task_id}
通过 task_id 查询任务状态和进度。
Path 参数
| 参数 | 类型 | 说明 |
|---|---|---|
task_id | string | 任务唯一标识 |
Response 200 — 处理中
{
"task_id": "a1b2c3d4-...",
"status": "processing",
"progress": 65,
"created_at": "2026-08-03T10:30:00Z",
"started_at": "2026-08-03T10:30:01Z",
"type": "compress",
"input_filename": "model.glb",
"input_size_bytes": 15728640
}Response 200 — 已完成
{
"task_id": "a1b2c3d4-...",
"status": "completed",
"progress": 100,
"created_at": "2026-08-03T10:30:00Z",
"completed_at": "2026-08-03T10:30:05Z",
"type": "compress",
"input_filename": "model.glb",
"input_size_bytes": 15728640,
"output": {
"filename": "model_optimized.glb",
"size_bytes": 3145728,
"compression_ratio": 0.20,
"savings_percent": 80.0
}
}Response 200 — 失败
{
"task_id": "a1b2c3d4-...",
"status": "failed",
"error": "draco_transcoder execution failed: exit code 1",
"created_at": "2026-08-03T10:30:00Z",
"failed_at": "2026-08-03T10:30:02Z"
}响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
task_id | string | 任务唯一标识 |
status | string | pending / processing / completed / failed |
progress | integer | 进度 0-100 |
type | string | compress / convert / repair / diagnose / texture_optimize / texture_ktx2 |
input_filename | string | 原始文件名 |
input_size_bytes | integer | 原始大小(字节) |
output.filename | string | 输出文件名(completed 时) |
output.size_bytes | integer | 输出大小(字节)(completed 时) |
output.compression_ratio | float | 压缩比(compress/texture 类) |
output.savings_percent | float | 体积减少百分比(compress/texture 类) |
error | string | 错误原因(failed 时) |
created_at | string | 创建时间 ISO 8601 |
started_at | string | 开始时间 |
completed_at / failed_at | string | 结束时间 |
GET /api/v1/tasks/{task_id}/download
下载处理后的结果文件。
Path 参数
| 参数 | 类型 | 说明 |
|---|---|---|
task_id | string | 已完成的任务 ID |
Response 200
返回文件二进制流(Content-Type: application/octet-stream)。
八、批量处理
POST /api/v1/batch/compress
一次提交多个文件压缩,每个独立生成子任务。
Headers
| Header | 值 |
|---|---|
| Content-Type | multipart/form-data |
| X-API-Key | 你的密钥 |
Body (form-data)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
files | File[] | ✅ | 多个模型文件 |
engine | string | ✅ | draco 或 meshopt |
level | integer | ❌ | 压缩级别 1-10,默认 7 |
Response 200
{
"batch_id": "batch-abc123",
"total": 3,
"tasks": [
{ "task_id": "t1-...", "filename": "model1.glb", "status": "pending" },
{ "task_id": "t2-...", "filename": "model2.fbx", "status": "pending" },
{ "task_id": "t3-...", "filename": "scene.gltf", "status": "pending" }
]
}GET /api/v1/batch/{batch_id}
查询批次整体进度。
Path 参数
| 参数 | 类型 | 说明 |
|---|---|---|
batch_id | string | 批次唯一标识 |
Response 200
{
"batch_id": "batch-abc123",
"status": "processing",
"total": 3, "completed": 1, "failed": 0,
"tasks": [
{ "task_id": "t1-...", "filename": "model1.glb", "status": "completed" },
{ "task_id": "t2-...", "filename": "model2.fbx", "status": "processing" },
{ "task_id": "t3-...", "filename": "scene.gltf", "status": "pending" }
]
}九、授权
POST /api/v1/license/verify
验证 License Key 是否有效。
Body (JSON)
{ "license_key": "xxxx-xxxx-xxxx-xxxx" }Response 200
{
"valid": true,
"tier": "pro",
"expires_at": "2027-08-03T00:00:00Z",
"limits": { "max_file_size_mb": 500, "max_batch_count": 100 }
}GET /api/v1/license/info
查询当前授权状态。
Response 200
{
"mode": "licensed",
"tier": "enterprise",
"license_key": "****-****-****-1234",
"expires_at": "2027-12-31T00:00:00Z",
"trial": { "enabled": true, "used_files": 12, "max_files": 50 },
"limits": {
"max_file_size_mb": 500,
"max_batch_count": -1,
"max_texture_size_mb": 500
}
}
-1表示无限制。
十、监控
GET /api/v1/metrics
Prometheus 格式监控指标,可用于 Grafana 集成。
| 指标名 | 含义 |
|---|---|
zipoly_tasks_total | 任务总数(按 type/status 分) |
zipoly_task_duration_seconds | 任务耗时分布 |
zipoly_files_processed_total | 已处理文件总数 |
zipoly_compression_ratio | 压缩比分布 |
zipoly_active_tasks_gauge | 当前并发任务数 |
错误码
| HTTP | 含义 | 典型场景 |
|---|---|---|
| 400 | 参数错误 | 不支持的格式、缺少必填字段 |
| 401 | 未授权 | 缺少/错误的 X-API-Key |
| 404 | 不存在 | task_id / batch_id 无效 |
| 413 | 文件过大 | 超出套餐限制 |
| 429 | 限流 | 超过每分钟请求次数 |
| 500 | 内部错误 | 引擎执行失败、磁盘不足 |
错误响应格式
{ "error": "错误描述信息" }| 场景 | 示例 |
|---|---|
| 不支持的格式 | { "error": "unsupported format: .max" } |
| 缺少必填字段 | { "error": "missing required field: engine" } |
| 未授权 | { "error": "unauthorized: missing or invalid X-API-Key header" } |
| 文件过大 | { "error": "file size 512MB exceeds limit of 500MB for current license tier" } |
| 限流 | { "error": "rate limit exceeded: max 60 requests per minute per API key" } |
| 内部错误 | { "error": "internal error: draco_transcoder execution failed" } |
速率限制
每个 Key 每分钟最多 60 次请求。超限返回 429,响应头:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1691123456可通过 ZIPOLY__SERVER__RATE_LIMIT_PER_MINUTE 调整,详见配置参考。