Creative Lab — Fidget Pixel API
将一张源照片分两个阶段转换为可多色 3D 打印的像素艺术指尖玩具板:**prototype(原型)**阶段将你的照片像素化为像素艺术图像,然后
**build(构建)**阶段将该图像采样到 16×16 或 32×32 的网格上,并将每个像素转化为一个可互锁的方形或六边形零件,最终以单个 3MF 文件交付,其中的对象携带各自的颜色信息,以便多料丝 slicer 能够为每个零件打印出正确的颜色。这两个阶段通过 input_task_id 关联。
POST /openapi/creative-lab/fidget-pixel/v1/prototypePOST /openapi/creative-lab/fidget-pixel/v1/build
两个 POST endpoint 均需要付费 subscription 计划。免费计划账户发起的请求将被拒绝,并返回 402 Payment Required。
创建一个 Fidget Pixel 原型任务
根据源照片生成一张像素艺术图像。返回的任务
ID 就是你在调用构建 endpoint 时作为 input_task_id
传入的值。如果结果不是你想要的,可以再次调用该
endpoint 生成另一次结果——每次调用都会单独计费。响应结构请参考
Fidget Pixel Prototype 任务对象。
参数
- Name
- image_url
- Type
- string
- 必选
- Description
供 Meshy 像素化处理的源照片。目前我们支持
.jpg、.jpeg、.png和.webp格式。格式是通过解码图像数据来检测的,而不是根据 URL 的文件扩展名——即使 URL 没有扩展名,或者会发生重定向,只要解码后的字节符合支持的格式即可正常使用。系统会自动跟随 HTTP 重定向。
提供图像有两种方式:
- 可公开访问的 URL:一个可以从公共互联网访问到的 URL。
- Data URI:图像的 base64 编码 data URI。data URI 示例:
data:image/jpeg;base64,<your base64-encoded image data>。
- Name
- type
- Type
- string
- 必选
- Description
照片展示的内容。该参数决定像素化风格,因此请谨慎选择——两种取值会产生明显不同的效果。可选值:
person— 主体是人物(肖像或全身)。生成主体的 Q 版风格像素精灵。other— 其他任何内容:宠物、物品、吉祥物、徽标、风景。生成主体的拼豆艺术风格像素图标。
- Name
- name
- Type
- string
- Description
用于展示目的的可选任务名称。最多 100 个字符。
返回值
响应的 result 属性包含新创建的 fidget pixel 原型任务的任务 id。轮询 获取任务 endpoint,或订阅 stream,直到任务状态变为 SUCCEEDED,然后将该 ID 作为 input_task_id 传递给 构建 endpoint。
失败模式
- Name
400 - Bad Request- Description
请求内容不可接受。常见原因:
- 缺少参数:
image_url和type均为必填项。 - type 无效:
type必须为person或other。 - 图像格式无效:提供的
image_url不是受支持的格式(.jpg、.jpeg、.png、.webp)。 - 图像尺寸超出范围:图像过小、超出最大文件大小限制,或超出最大像素数限制。
- URL 无法访问:无法下载
image_url(404 或 timeout)。 - Data URI 无效:base64 字符串格式错误。
- 内容被标记:输入图像被 NSFW moderation 标记。
- 缺少参数:
- Name
401 - Unauthorized- Description
身份验证失败。请检查你的 API key。
- Name
402 - Payment Required- Description
credits 不足以执行此任务,或该 API key 属于免费套餐账户。
- Name
403 - Forbidden- Description
输入图像被知识产权 moderation 标记(
Content flagged for intellectual property violation)。仅启用了知识产权过滤功能的企业版账户会被阻止;不会产生任何费用。
- Name
429 - Too Many Requests- Description
你已超出速率限制。
- Name
500 - Internal Server Error- Description
知识产权检查本身未能完成(
Unable to perform intellectual property check, please try again)。启用了知识产权过滤功能的企业版账户在此项检查失败时会采取保守策略(fail closed);不会产生任何费用——请重试该请求。
Request
# Stage 1: pixelize the source photo
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype \
-X POST \
-H "Authorization: Bearer ${YOUR_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"image_url": "<your publicly accessible image url or base64-encoded data URI>",
"type": "person"
}'
Response
{
"result": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7"
}
创建 Fidget Pixel 构建任务
根据一个已成功的原型任务生成可 3D 打印的部件。构建过程会将原型的像素画图像采样到所请求的网格上,将其量化为最多 color_count 种颜色,并为每个网格单元生成一个互锁部件。最终产物是一个单独的 3MF 文件,其中每个部件都是一个带有其颜色标签的独立对象,可直接用于多耗材 slicer。响应结构请参见
Fidget Pixel 构建任务对象。
参数
- Name
- input_task_id
- Type
- string
- 必选
- Description
通过同一个 OpenAPI endpoint 创建的原型任务的任务 ID。该原型必须由同一个 Meshy 账户创建,且必须已达到
SUCCEEDED状态。通过 webapp 创建的原型任务不被接受——构建 endpoint 仅接受由
POST /openapi/creative-lab/fidget-pixel/v1/prototype生成的原型任务,其他任何来源都会被拒绝并返回404。
- Name
- name
- Type
- string
- Description
可选的任务名称,用于显示目的。最多 100 个字符。
options
可选的部件 geometry 设置。每个字段都有默认值——仅需发送你想覆盖的字段。这些控件与 Creative Lab webapp 中暴露的控件相同;插销高度、顶盖比例以及其他制造预设均由 shape 和 piece_size_mm 推导得出,不对外暴露。
- Name
- shape
- Type
- string
- 默认值 square
- Description
每个部件的外形轮廓。可用取值:
square(默认)—— 方形网格上的方形部件。hex—— 六边形网格上的六边形部件。六边形部件仅提供6和8毫米规格。
- Name
- grid_size
- Type
- integer
- 默认值 32
- Description
棋盘每边的部件数量。可用取值:
16或32。32网格保留更多细节;16网格意味着在相同主题下部件更少、更大。
- Name
- piece_size_mm
- Type
- integer
- 默认值 8
- Description
每个部件的边长,单位为毫米。可用取值:
6、8或10。该值与grid_size共同决定打印棋盘的大小——例如 32 × 8 毫米约为每边 26 厘米。shape: "hex"不支持10(大多数消费级 FDM 打印机上,倾斜的六边形面会出现悬垂问题)。
- Name
- color_count
- Type
- integer
- 默认值 8
- Description
图像量化调色板中的最大颜色数量。范围:
[1, 8]。每种颜色在你的 slicer 中对应一种耗材。
- Name
- piece_height_mm
- Type
- integer
- 默认值 15
- Description
每个部件的高度,单位为毫米。范围:
[10, 80]。
output
可选的输出格式选择器。默认为 3mf,目前这是唯一支持的取值。
- Name
- format
- Type
- string
- 默认值 3mf
- Description
构建返回的产物。可用取值:
3mf(默认)—— 在model_urls.3mf下返回单个model.3mf文件,每个部件对应一个对象,且每个对象都附带了部件颜色。
返回值
响应的 result 属性包含新创建的 fidget pixel 构建任务的任务 id。轮询 获取任务 endpoint 或订阅 流式接口,直到任务达到 SUCCEEDED 状态,然后从 model_urls.3mf 下载产物。
失败模式
- Name
400 - Bad Request- Description
请求不可接受。常见原因:
- 缺少参数:
input_task_id为必填项。 - 无效的 UUID:
input_task_id不是有效的 UUID。 - 父任务未成功:所引用的原型任务尚未达到
SUCCEEDED状态。 - 无候选结果:原型任务已成功,但未生成任何像素画图像;请创建一个新的原型。
- 选项超出范围:
options中的某个字段超出了其允许的取值集合或范围——例如options.grid_size must be 16 or 32,或options.piece_size_mm=10 is not supported for shape=hex; hex pieces are available in 6 and 8 mm。 - 不支持的格式:
output.format必须为3mf。
- 缺少参数:
- Name
401 - Unauthorized- Description
身份验证失败。请检查你的 API key。
- Name
402 - Payment Required- Description
执行此任务的 credits 不足,或该 API key 属于免费套餐账户。
- Name
403 - Forbidden- Description
所引用原型的图像被知识产权 moderation 标记。仅启用了知识产权过滤功能的 Enterprise 账户会被阻止;不会产生任何扣费。
- Name
404 - Not Found- Description
所引用的原型任务不存在、属于其他用户,或是通过 webapp 创建的(只有 API 模式下创建的原型任务才能串联到构建流程)。
- Name
429 - Too Many Requests- Description
你已超出速率限制。
- Name
500 - Internal Server Error- Description
无法确定所引用原型的知识产权判定结果(
Unable to perform intellectual property check, please try again)。启用了知识产权过滤功能的 Enterprise 账户在此项检查失败时会采取拒绝策略;不会产生任何扣费——请重试该请求。
Request
# Stage 2: chain build off a succeeded prototype task
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build \
-X POST \
-H "Authorization: Bearer ${YOUR_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"input_task_id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"options": {
"shape": "square",
"grid_size": 32,
"piece_size_mm": 8,
"color_count": 8,
"piece_height_mm": 15
},
"output": {
"format": "3mf"
}
}'
Response
{
"result": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98"
}
检索 Fidget Pixel 任务
根据有效的任务 id 检索原型(prototype)或构建(build)任务。URL 路径
必须与任务所处的阶段相匹配——通过 /prototype/:id 获取构建任务
会返回 404,反之亦然。
响应格式请参阅 Fidget Pixel 原型任务对象 和 Fidget Pixel 构建任务对象。
参数
- Name
- id
- Type
- path
- Description
要检索的 fidget pixel 任务的唯一标识符。
返回值
响应包含 fidget pixel 任务对象。其结构取决于 所请求的阶段。
失败模式
- Name
400 - Bad Request- Description
id不是有效的 UUID(Invalid ID)。
- Name
403 - Forbidden- Description
该任务的图像被知识产权审核(moderation)标记。仅启用了知识产权过滤功能的企业账户会被阻止。
- Name
404 - Not Found- Description
该任务不存在、属于其他用户,或其所处阶段与 URL 路径不匹配。
- Name
500 - Internal Server Error- Description
无法完成知识产权检查(
Unable to perform intellectual property check, please try again);启用了知识产权过滤功能的企业账户在此情况下会按失败关闭(fail closed)处理。请重试该请求。
Request
# Prototype
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
# Build
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Prototype Response
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
Build Response
{
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
删除 Fidget Pixel 任务
取消一个 fidget pixel 任务。如果任务仍处于 PENDING 状态,创建时消耗的
credits 将被退还。已经处于 IN_PROGRESS 状态的任务会被取消但不会退款
(工作进程可能已经在消耗资源)。已经达到终止状态
(SUCCEEDED、FAILED、CANCELED)的任务无法被取消。
URL 路径必须与任务所处的阶段匹配 —— 对
/prototype/:buildId 执行 DELETE 将返回 404。
路径参数
- Name
- id
- Type
- path
- Description
要取消的 fidget pixel 任务的唯一标识符。
返回值
成功时返回 204 No Content,响应体为空。
失败模式
- Name
400 - Bad Request- Description
请求无法被接受。常见原因:
- 无效的 ID:
id不是一个有效的 UUID。 - 终止状态:任务已经处于
SUCCEEDED、FAILED或CANCELED状态,无法被取消。
- 无效的 ID:
- Name
404 - Not Found- Description
该任务不存在、属于其他用户,或其所处阶段与 URL 路径不匹配。
Request
curl --request DELETE \
--url https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response
// Returns 204 No Content on success (empty body).
流式获取 Fidget Pixel 任务
通过 Server-Sent Events(SSE)流式获取 fidget pixel 任务的实时更新。
URL 路径必须与任务所处的阶段匹配 —— 在
/prototype/:buildId/stream 处打开流会发出一个 event: error
payload,其 status_code: 404,随后关闭该流;格式错误的 id 也会发生同样的情况,
但 status_code: 400(Invalid ID)。
参数
- Name
- id
- Type
- path
- Description
要进行流式获取的 fidget pixel 任务的唯一标识符。
返回值
以 Server-Sent Events 的形式返回一系列 Fidget Pixel Prototype
或 Fidget Pixel Build 任务对象。
每一帧都携带该阶段的完整任务对象 —— 与 Get
endpoint 返回的形状相同 —— 因此当任务处于 PENDING 或 IN_PROGRESS
状态时,输出字段只是尚未被填充(为 null、[] 或 {}),且
finished_at 为 null。
Request
curl -N https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/stream \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response Stream
// Error event example (wrong stage or task not found)
event: error
data: {
"status_code": 404,
"message": "Task not found"
}
// Message event examples illustrate task progress.
// Every frame is the full task object for the stage; fields not yet populated are null / empty.
event: message
data: {
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "PENDING",
"progress": 0,
"created_at": 1757001300000,
"started_at": null,
"finished_at": null,
"expires_at": 1757260500000,
"preceding_tasks": 2,
"task_error": null,
"consumed_credits": 30,
"model_urls": {}
}
event: message
data: {
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
获取 Fidget Pixel 任务列表
获取你在单个阶段的 fidget pixel 任务的分页列表。
URL 路径用于选择阶段——/prototype 返回 prototype 任务;
/build 返回 build 任务。另一个阶段的任务不会包含在
任一响应中。
路径参数
- Name
- stage
- Type
- path
- 必选
- Description
prototype或build二者之一。该集合仅返回 阶段与 URL 相匹配的任务——请求/prototype永远不会返回 build 任务,反之亦然。
查询参数
- Name
- page_num
- Type
- integer
- 默认值 1
- Description
用于分页的页码。
- Name
- page_size
- Type
- integer
- 默认值 10
- Description
每页大小限制。最大允许值为
100项。
- Name
- sort_by
- Type
- string
- 默认值 -created_at
- Description
排序所依据的字段。可用值:
+created_at:按创建时间升序排序。-created_at:按创建时间降序排序。
返回值
返回该阶段任务对象的分页列表——列出 /prototype 时为
the fidget pixel prototype task object,
列出 /build 时为
the fidget pixel build task object。
Request
# List prototype tasks
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype?page_size=10 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
# List build tasks
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build?page_size=10 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response (List Prototype Tasks)
[
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
]
Fidget Pixel 原型任务对象
Fidget Pixel 原型任务对象是 Meshy 用于跟踪将源照片像素化为像素艺术图像的工作单元。此阶段的输出会通过 input_task_id 链接到构建阶段。
属性
- Name
- id
- Type
- string
- Description
任务的唯一标识符。虽然我们在实现细节上使用 k-可排序的 UUID 作为任务 id,但你不应对 id 的格式做任何假设。
- Name
- type
- Type
- string
- Description
任务的类型。该值为
creative-lab-fidget-pixel-prototype。
- Name
- name
- Type
- string
- Description
创建任务时提供的任务名称。如果没有提供名称,则为空字符串。
- Name
- status
- Type
- string
- Description
任务的状态。可能的值为
PENDING、IN_PROGRESS、SUCCEEDED、FAILED、CANCELED之一。
- Name
- progress
- Type
- integer
- Description
任务的进度。如果任务尚未开始,此属性将为
0。任务成功后,此值将变为100。
- Name
- created_at
- Type
- timestamp
- Description
任务创建时的 timestamp,以毫秒为单位。
timestamp 表示自 1970 年 1 月 1 日 UTC 起经过的毫秒数,遵循 RFC 3339
标准。 例如,2023 年 9 月 1 日星期五 GMT 时间中午 12:00:00 表示为1693569600000。这适用于 Meshy API 中的所有 timestamp。
- Name
- started_at
- Type
- timestamp
- Description
任务开始时的 timestamp,以毫秒为单位。如果任务尚未开始,此属性将为
null。
- Name
- finished_at
- Type
- timestamp
- Description
任务完成时的 timestamp,以毫秒为单位。如果任务尚未完成,此属性将为
null。
- Name
- expires_at
- Type
- timestamp
- Description
任务结果过期时的 timestamp,以毫秒为单位——即任务完成后 3 天。企业账户会无限期保留 API 结果(参见资产保留期);对于这类账户,此 timestamp 会被设置为大约 100 年之后。
- Name
- preceding_tasks
- Type
- integer
- Description
前置任务的数量。
只有当任务状态为
PENDING时,此字段的值才有意义。
- Name
- task_error
- Type
- object
- Description
失败任务的错误详情。完整的
task_error对象参考请参见Errors。
- Name
- consumed_credits
- Type
- integer
- Description
该任务消耗的 credits 数量。达到
SUCCEEDED状态的任务会按其所属阶段全额扣费。从未被创建的任务(请求时返回4xx,包括被 moderation 拒绝的情况)完全不会扣费。达到FAILED状态的任务返回0——扣费会被退还。通过DELETE取消任务只有在任务仍处于PENDING状态时才会退款;已处于IN_PROGRESS状态的任务仍会被扣费,因为相关工作已经产生。
- Name
- image_urls
- Type
- array of strings
- Description
此原型任务生成的像素艺术图像的可下载 URL。目前 API 始终恰好返回一张图像;该字段之所以设计为数组,是为了让未来的版本能够在不引入破坏性变更的情况下呈现多个候选结果。在任务达到
SUCCEEDED之前该字段为空。这些是签名 URL:获取时无需携带
Authorization请求头。它们在expires_at(即finished_at之后 3 天)之前始终有效,在此期间重新读取任务会返回相同的 URL,而不是重新签名的新 URL。请在此之前自行下载并保存文件——过期的链接无法刷新。
Example Fidget Pixel Prototype Task Object
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
Fidget Pixel 构建任务对象
Fidget Pixel 构建任务对象是 Meshy 用来跟踪的一个工作单元,用于从已成功完成的原型任务生成可打印的部件。构建过程会将原型的像素艺术图像采样到所请求的网格上,并发布一个带颜色标签的 3MF 文件。
属性
- Name
- id
- Type
- string
- Description
任务的唯一标识符。
- Name
- type
- Type
- string
- Description
任务的类型。该值为
creative-lab-fidget-pixel-build。
- Name
- name
- Type
- string
- Description
创建任务时提供的任务名称。如果未提供名称,则为空字符串。
- Name
- status
- Type
- string
- Description
任务的状态。可能的取值为
PENDING、IN_PROGRESS、SUCCEEDED、FAILED、CANCELED之一。
- Name
- progress
- Type
- integer
- Description
任务的进度。如果任务尚未开始,此属性为
0。一旦任务成功完成,该值将变为100。
- Name
- created_at
- Type
- timestamp
- Description
任务创建时的时间戳,单位为毫秒。
- Name
- started_at
- Type
- timestamp
- Description
任务开始时的时间戳,单位为毫秒。在任务开始之前为
null。
- Name
- finished_at
- Type
- timestamp
- Description
任务完成时的时间戳,单位为毫秒。在任务完成之前为
null。
- Name
- expires_at
- Type
- timestamp
- Description
任务结果过期时的时间戳,单位为毫秒——即任务完成后的 3 天。企业账户会无限期保留 API 结果(参见资产保留期);对于企业账户,此时间戳会被设置为约 100 年之后。
- Name
- preceding_tasks
- Type
- integer
- Description
排在前面的任务数量。仅当状态为
PENDING时才有意义。
- Name
- task_error
- Type
- object
- Description
失败任务的错误详情。完整的
task_error对象参考请参见 Errors。
- Name
- consumed_credits
- Type
- integer
- Description
此任务消耗的 credits 数量。达到
SUCCEEDED状态的任务将被收取其阶段的全部费用。从未成功创建的任务(请求时返回4xx,包括 moderation 拒绝的情况)不会产生任何费用。达到FAILED状态的任务返回0——费用会被退还。通过DELETE取消任务只有在任务仍处于PENDING状态时才会退款;已经处于IN_PROGRESS状态的任务仍会被收费,因为相应的工作已经产生。
- Name
- model_urls
- Type
- object
- Description
按格式索引的、可下载生成产物的 URL。仅包含一个条目——即通过构建请求中的
output.format所请求的格式。在任务达到SUCCEEDED状态之前为空。这些是签名 URL:获取时不要携带
Authorization头。它们在expires_at(即finished_at之后 3 天)之前一直有效,在此期间内重新读取任务会返回相同的 URL,而不是重新签名的新 URL。请在此之前自行下载并保存文件——过期的链接无法刷新。- Name
3mf- Type
- string
- Description
3MF 文件的可下载 URL。每个部件对应一个对象,并以其调色板颜色进行标记,因此支持多耗材的 slicer 可以按颜色分配耗材。当
output.format为3mf(默认值)时会出现此字段。
Example Fidget Pixel Build Task Object
{
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
端到端示例
完整流程:从一张照片创建原型,轮询直到状态变为 SUCCEEDED,基于该原型创建构建任务,轮询构建任务直到状态变为
SUCCEEDED,然后从 model_urls 下载 3MF 文件。
原型通常在几分钟内完成;构建任务通常在一分钟以内即可完成。在实际集成中,你应该把原型的
image_urls 条目展示给最终用户,让他们确认(或重新运行原型)之后,再在构建任务上花费 credits。
Complete flow
#!/usr/bin/env bash
set -euo pipefail
# Requires curl and jq. Point IMAGE_PATH at a local photo, or IMAGE_URL at a public one:
# export MESHY_API_KEY=msy_...
# export IMAGE_PATH=./portrait.jpg # or: export IMAGE_URL=https://...
# export PIXEL_TYPE=person # or: other
: "${MESHY_API_KEY:?export MESHY_API_KEY first}"
if [[ -z "${IMAGE_PATH:-}" && -z "${IMAGE_URL:-}" ]]; then
echo "export IMAGE_PATH (local file) or IMAGE_URL (public url) first" >&2
exit 1
fi
PIXEL_TYPE=${PIXEL_TYPE:-person}
BASE="https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1"
AUTH="Authorization: Bearer $MESHY_API_KEY"
# api METHOD URL [curl args...] -> prints the response body, non-zero on failure.
# Note we do not use -f/--fail: it discards the body, and the body is the only
# place the reason appears.
api() {
local method=$1 url=$2 out http_code body
shift 2
out=$(curl --silent --show-error --max-time 60 --write-out $'\n%{http_code}' \
-X "$method" "$url" -H "$AUTH" "$@") || return 1
http_code=${out##*$'\n'}
body=${out%$'\n'*}
if ((http_code >= 400)); then
echo "HTTP $http_code for $url: $body" >&2
return 1
fi
printf '%s' "$body"
}
# Each task gets its own 40-minute budget.
poll() {
local kind=$1 id=$2 delay=5 task_status deadline
deadline=$(($(date +%s) + 2400))
while :; do
if (($(date +%s) >= deadline)); then
echo "gave up waiting for $kind $id" >&2
return 1
fi
task_status=$(api GET "$BASE/$kind/$id" | jq -r '.status')
echo "$kind: $task_status"
case "$task_status" in
SUCCEEDED) return 0 ;;
FAILED | CANCELED) return 1 ;;
esac
sleep "$delay"
delay=$((delay * 2 > 30 ? 30 : delay * 2))
done
}
# Build the request body in a file. A base64 data URI must never go on the
# command line or into an exported variable - a photo of any real size will
# exceed the OS argument limit.
BODY=$(mktemp)
trap 'rm -f "$BODY"' EXIT
if [[ -n "${IMAGE_PATH:-}" ]]; then
# Declare the real type: the API accepts JPEG, PNG and WebP.
case "$(printf '%s' "${IMAGE_PATH##*.}" | tr 'A-Z' 'a-z')" in
png) MIME=image/png ;;
webp) MIME=image/webp ;;
*) MIME=image/jpeg ;;
esac
{
printf '{"type":"%s","image_url":"data:%s;base64,' "$PIXEL_TYPE" "$MIME"
base64 <"$IMAGE_PATH" | tr -d '\n'
printf '"}'
} >"$BODY"
else
jq -n --arg t "$PIXEL_TYPE" --arg u "$IMAGE_URL" \
'{type: $t, image_url: $u}' >"$BODY"
fi
# 1. Create the prototype task
PROTO_ID=$(api POST "$BASE/prototype" \
-H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')
# 2. Wait for the pixel-art image (show image_urls[0] to a user in production)
poll prototype "$PROTO_ID"
# 3. Create the build task (defaults: square pieces, 32x32 grid, 8 mm, 8 colors, 15 mm tall)
jq -n --arg p "$PROTO_ID" \
'{input_task_id: $p, options: {shape: "square", grid_size: 32, piece_size_mm: 8, color_count: 8, piece_height_mm: 15}, output: {format: "3mf"}}' >"$BODY"
BUILD_ID=$(api POST "$BASE/build" \
-H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')
# 4. Wait for the pieces
poll build "$BUILD_ID"
# 5. Download the 3MF. This is a signed URL: no Authorization header,
# and it stays valid for 3 days after the task finishes.
TASK=$(api GET "$BASE/build/$BUILD_ID")
curl --silent --show-error --fail --max-time 900 \
-o fidget-pixel.3mf "$(jq -r '.model_urls["3mf"]' <<<"$TASK")"
echo "Done: fidget-pixel.3mf"