Creative Lab — Fidget Pixel API

将一张源照片分两个阶段转换为可多色 3D 打印的像素艺术指尖玩具板:**prototype(原型)**阶段将你的照片像素化为像素艺术图像,然后 **build(构建)**阶段将该图像采样到 16×16 或 32×32 的网格上,并将每个像素转化为一个可互锁的方形或六边形零件,最终以单个 3MF 文件交付,其中的对象携带各自的颜色信息,以便多料丝 slicer 能够为每个零件打印出正确的颜色。这两个阶段通过 input_task_id 关联。

  • POST /openapi/creative-lab/fidget-pixel/v1/prototype
  • POST /openapi/creative-lab/fidget-pixel/v1/build

POST/openapi/creative-lab/fidget-pixel/v1/prototype

创建一个 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_urltype 均为必填项。
    • type 无效type 必须为 personother
    • 图像格式无效:提供的 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

POST
/openapi/creative-lab/fidget-pixel/v1/prototype
# 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"
}

POST/openapi/creative-lab/fidget-pixel/v1/build

创建 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 中暴露的控件相同;插销高度、顶盖比例以及其他制造预设均由 shapepiece_size_mm 推导得出,不对外暴露。

  • Name
    shape
    Type
    string
    默认值 square
    Description

    每个部件的外形轮廓。可用取值:

    • square(默认)—— 方形网格上的方形部件。
    • hex —— 六边形网格上的六边形部件。六边形部件仅提供 68 毫米规格。
  • Name
    grid_size
    Type
    integer
    默认值 32
    Description

    棋盘每边的部件数量。可用取值:163232 网格保留更多细节;16 网格意味着在相同主题下部件更少、更大。

  • Name
    piece_size_mm
    Type
    integer
    默认值 8
    Description

    每个部件的边长,单位为毫米。可用取值:6810。该值与 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 为必填项。
    • 无效的 UUIDinput_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

POST
/openapi/creative-lab/fidget-pixel/v1/build
# 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"
}

GET/openapi/creative-lab/fidget-pixel/v1/(prototype|build)/:id

检索 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

GET
/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7
# 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=***"
  }
}

DELETE/openapi/creative-lab/fidget-pixel/v1/(prototype|build)/:id

删除 Fidget Pixel 任务

取消一个 fidget pixel 任务。如果任务仍处于 PENDING 状态,创建时消耗的 credits 将被退还。已经处于 IN_PROGRESS 状态的任务会被取消但不会退款 (工作进程可能已经在消耗资源)。已经达到终止状态 (SUCCEEDEDFAILEDCANCELED)的任务无法被取消。

URL 路径必须与任务所处的阶段匹配 —— 对 /prototype/:buildId 执行 DELETE 将返回 404

路径参数

  • Name
    id
    Type
    path
    Description

    要取消的 fidget pixel 任务的唯一标识符。

返回值

成功时返回 204 No Content,响应体为空。

失败模式

  • Name
    400 - Bad Request
    Description

    请求无法被接受。常见原因:

    • 无效的 IDid 不是一个有效的 UUID。
    • 终止状态:任务已经处于 SUCCEEDEDFAILEDCANCELED 状态,无法被取消。
  • Name
    404 - Not Found
    Description

    该任务不存在、属于其他用户,或其所处阶段与 URL 路径不匹配。

Request

DELETE
/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7
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).

GET/openapi/creative-lab/fidget-pixel/v1/(prototype|build)/:id/stream

流式获取 Fidget Pixel 任务

通过 Server-Sent Events(SSE)流式获取 fidget pixel 任务的实时更新。 URL 路径必须与任务所处的阶段匹配 —— 在 /prototype/:buildId/stream 处打开流会发出一个 event: error payload,其 status_code: 404,随后关闭该流;格式错误的 id 也会发生同样的情况, 但 status_code: 400Invalid ID)。

参数

  • Name
    id
    Type
    path
    Description

    要进行流式获取的 fidget pixel 任务的唯一标识符。

返回值

以 Server-Sent Events 的形式返回一系列 Fidget Pixel PrototypeFidget Pixel Build 任务对象。 每一帧都携带该阶段的完整任务对象 —— 与 Get endpoint 返回的形状相同 —— 因此当任务处于 PENDINGIN_PROGRESS 状态时,输出字段只是尚未被填充(为 null[]{}),且 finished_atnull

Request

GET
/openapi/creative-lab/fidget-pixel/v1/build/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/stream
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=***"
  }
}

GET/openapi/creative-lab/fidget-pixel/v1/(prototype|build)

获取 Fidget Pixel 任务列表

获取你在单个阶段的 fidget pixel 任务的分页列表。 URL 路径用于选择阶段——/prototype 返回 prototype 任务; /build 返回 build 任务。另一个阶段的任务不会包含在 任一响应中。

路径参数

  • Name
    stage
    Type
    path
    必选
    Description

    prototypebuild 二者之一。该集合仅返回 阶段与 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

GET
/openapi/creative-lab/fidget-pixel/v1/prototype
# 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

    任务的状态。可能的值为 PENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELED 之一。

  • Name
    progress
    Type
    integer
    Description

    任务的进度。如果任务尚未开始,此属性将为 0。任务成功后,此值将变为 100

  • Name
    created_at
    Type
    timestamp
    Description

    任务创建时的 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

    前置任务的数量。

  • 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

    任务的状态。可能的取值为 PENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELED 之一。

  • 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.format3mf(默认值)时会出现此字段。

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

POST
/openapi/creative-lab/fidget-pixel/v1
#!/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"