# 产品全案素材 - 外部接口文档 > 本文档供外部任务系统对接使用 ## 概述 素材平台提供外部接口,允许任务系统通过任务号查询、下载和删除产品全案素材。 ### 基础信息 - **接口地址**: `https://your-domain.com/api/external/` - **鉴权方式**: API Key(请求头 `X-API-Key`) - **数据格式**: JSON ### 调用流程 ``` 1. 任务系统生成任务编号(如 TASK202601030184) 2. 员工在素材平台上传素材时填入任务号 3. 员工在任务系统点击「完成」 4. 任务系统调用查询接口获取素材详情和下载链接 5. 任务系统通过下载链接获取文件 6. (可选)任务完成后调用删除接口清理素材 ``` --- ## 接口列表 ### 1. 查询素材详情 通过任务号查询素材详情,获取下载链接。 **请求** ``` GET /api/external/product-assets?taskNo={任务号} ``` **请求头** | 参数 | 类型 | 必填 | 说明 | |-----|------|-----|------| | X-API-Key | string | 是 | API 访问密钥 | **请求参数** | 参数 | 类型 | 必填 | 说明 | |-----|------|-----|------| | taskNo | string | 是 | 任务号,格式:TASK + 12位数字 | **响应示例(成功)** ```json { "success": true, "data": { "taskNo": "TASK202601030184", "productModel": "YYD-001", "categoryName": "天猫旗舰店", "sceneName": "客厅场景", "status": "fetched", "createdAt": "2026-01-03T10:00:00.000Z", "updatedAt": "2026-01-03T10:30:00.000Z", "assets": { "main": [ { "id": "asset-uuid-1", "url": "https://s3.yydd.ai/...", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx", "fileName": "主图1.jpg", "fileSize": 1024000 } ], "sku": [ { "id": "asset-uuid-2", "url": "https://s3.yydd.ai/...", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx", "fileName": "SKU白色.jpg", "fileSize": 512000 } ], "detail": [ { "id": "asset-uuid-3", "url": "https://s3.yydd.ai/...", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx", "fileName": "详情1.jpg", "fileSize": 2048000, "sortOrder": 0 }, { "id": "asset-uuid-4", "url": "https://s3.yydd.ai/...", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx", "fileName": "详情2.jpg", "fileSize": 1536000, "sortOrder": 1 } ], "psd": [ { "id": "asset-uuid-5", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx&assetId=asset-uuid-5", "fileName": "源文件1.psd", "fileSize": 52428800 }, { "id": "asset-uuid-6", "downloadUrl": "https://your-domain.com/api/external/download?token=xxx&assetId=asset-uuid-6", "fileName": "源文件2.psd", "fileSize": 31457280 } ] }, "downloadUrls": { "all": "https://your-domain.com/api/external/download?token=xxx", "main": "https://your-domain.com/api/external/download?token=xxx", "sku": "https://your-domain.com/api/external/download?token=xxx", "detail": "https://your-domain.com/api/external/download?token=xxx", "psd": "https://your-domain.com/api/external/download?token=xxx" } } } ``` **响应字段说明** | 字段 | 类型 | 说明 | |-----|------|------| | taskNo | string | 任务号 | | productModel | string | SPU型号 | | categoryName | string | 店铺名称 | | sceneName | string | 场景类别(可能为空) | | status | string | 状态:completed/fetched | | assets.main | array | 主图列表 | | assets.sku | array | SKU图列表 | | assets.detail | array | 详情图列表(按 sortOrder 排序) | | assets.psd | array | PSD源文件列表(可能为空数组) | | downloadUrls.all | string | 全部打包下载链接(不含PSD) | | downloadUrls.main | string | 主图打包下载链接 | | downloadUrls.sku | string | SKU图打包下载链接 | | downloadUrls.detail | string | 详情图打包下载链接 | | downloadUrls.psd | string/null | PSD批量下载链接(已废弃,请使用单个PSD文件的downloadUrl) | **响应示例(失败)** ```json { "success": false, "error": { "code": "TASK_NOT_FOUND", "message": "任务号不存在" } } ``` --- ### 2. 下载文件 通过下载链接获取文件。 **请求** ``` GET /api/external/download?token={下载令牌} ``` **请求参数** | 参数 | 类型 | 必填 | 说明 | |-----|------|-----|------| | token | string | 是 | 下载令牌(从查询接口获取) | **响应** - 成功:返回文件流(Content-Type 根据文件类型设置) - 打包下载:返回 ZIP 文件 **响应头示例** ``` Content-Type: application/zip Content-Disposition: attachment; filename="TASK202601030184-all.zip" ``` **错误响应** ```json { "success": false, "error": { "code": "TOKEN_EXPIRED", "message": "下载链接已过期,请重新查询获取新链接" } } ``` --- ### 3. 删除素材 删除指定任务号的素材(软删除)。 **请求** ``` DELETE /api/external/product-assets?taskNo={任务号} ``` **请求头** | 参数 | 类型 | 必填 | 说明 | |-----|------|-----|------| | X-API-Key | string | 是 | API 访问密钥 | **请求参数** | 参数 | 类型 | 必填 | 说明 | |-----|------|-----|------| | taskNo | string | 是 | 任务号 | **响应示例(成功)** ```json { "success": true, "message": "素材已删除", "data": { "taskNo": "TASK202601030184", "deletedAt": "2026-01-03T15:00:00.000Z" } } ``` --- ## 错误码 | 错误码 | HTTP状态码 | 说明 | |-------|-----------|------| | INVALID_API_KEY | 401 | API Key 无效或缺失 | | TASK_NOT_FOUND | 404 | 任务号不存在 | | MATERIAL_DELETED | 410 | 素材已被删除 | | TOKEN_EXPIRED | 401 | 下载令牌已过期(有效期24小时) | | INVALID_TOKEN | 401 | 下载令牌无效 | | INVALID_TASK_NO | 400 | 任务号格式错误 | | SERVER_ERROR | 500 | 服务器内部错误 | --- ## 注意事项 ### 下载链接有效期 - 下载链接(downloadUrl)有效期为 **24小时** - 过期后需重新调用查询接口获取新链接 - 建议在下载前先调用查询接口获取最新链接 ### 任务号格式 - 格式:`TASK` + 12位数字 - 示例:`TASK202601030184` - 任务号在系统中唯一,重复上传会报错 ### 任务状态说明 | 状态 | 说明 | |-----|------| | completed | 素材上传完成,等待获取 | | fetched | 已被外部系统查询过 | 首次查询成功后,状态会从 `completed` 变为 `fetched`。 ### 打包下载说明 - `downloadUrls.all` 包含:主图 + SKU图 + 详情图(**不含PSD**) - 如需下载 PSD,请单独使用 `downloadUrls.psd` - ZIP 文件内按文件夹分类:`main/`、`sku/`、`detail/` ### 调用频率限制 - 建议单个 API Key 每分钟不超过 60 次请求 - 超出限制可能返回 429 错误 --- ## 示例代码 ### Node.js ```javascript const axios = require('axios'); const API_BASE = 'https://your-domain.com/api/external'; const API_KEY = 'your-api-key'; // 查询素材 async function queryAssets(taskNo) { const response = await axios.get(`${API_BASE}/product-assets`, { params: { taskNo }, headers: { 'X-API-Key': API_KEY } }); return response.data; } // 下载文件 async function downloadFile(downloadUrl, savePath) { const response = await axios.get(downloadUrl, { responseType: 'stream' }); const writer = fs.createWriteStream(savePath); response.data.pipe(writer); return new Promise((resolve, reject) => { writer.on('finish', resolve); writer.on('error', reject); }); } // 使用示例 async function main() { const result = await queryAssets('TASK202601030184'); if (result.success) { // 下载全部(不含PSD) await downloadFile(result.data.downloadUrls.all, './assets.zip'); // 下载PSD if (result.data.downloadUrls.psd) { await downloadFile(result.data.downloadUrls.psd, './source.psd'); } } } ``` ### Python ```python import requests API_BASE = 'https://your-domain.com/api/external' API_KEY = 'your-api-key' def query_assets(task_no): response = requests.get( f'{API_BASE}/product-assets', params={'taskNo': task_no}, headers={'X-API-Key': API_KEY} ) return response.json() def download_file(download_url, save_path): response = requests.get(download_url, stream=True) with open(save_path, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) # 使用示例 result = query_assets('TASK202601030184') if result['success']: download_file(result['data']['downloadUrls']['all'], './assets.zip') ``` --- ## 联系方式 如有问题,请联系素材平台管理员获取 API Key 或技术支持。 --- *文档版本: 1.0* *更新日期: 2026-01-03*