Creative Lab — キーキャップ API

ソース写真をフルカラーのカスタムメカニカルキーボードキーキャップに変換するには、 2つの段階を経ます。プロトタイプは、入力写真から「完成したキーキャップ」の デザインレンダーを生成します。そのレンダーを確認したら、ビルドが1回の実行で それをテクスチャ付きの3Dキーキャップモデルに変換します——ホワイトモデル生成、 校正済みのデフォルトポーズでの自動的な着座とカット、フルモデルの着色、 そして最終アセンブリがすべて1つのビルドタスク内で行われます。この2つの段階は input_task_idcandidate_id によってリンクされています。

  • POST /openapi/creative-lab/keycap/v1/prototype
  • POST /openapi/creative-lab/keycap/v1/build

POST/openapi/creative-lab/keycap/v1/prototype

キーキャッププロトタイプタスクを作成する

元の写真から、完成したキーキャップデザインのレンダー画像を生成します。タスクの結果には、image_urls 配列(完成したキーキャップの表示用レンダー)と、それに対応する candidate_ids 配列が含まれます。どちらも1件のエントリのみを保持します。 結果が望んでいたものと異なる場合は、別のレンダーを得るためにこのエンドポイントを再度呼び出してください — 呼び出しごとに個別に課金されます。candidate_id をプロトタイプタスクIDとともに buildエンドポイントに渡してください。 レスポンスの形式については The Keycap Prototype Task Object を参照してください。

パラメータ

  • Name
    image_url
    Type
    string
    必須
    Description

    Meshyがキーキャップデザイン画像へ変換する元の写真です。現在サポートしている形式は .jpg.jpeg.png.webp です。

    形式は画像データをデコードして判定され、URLのファイル拡張子からは判定されません — 拡張子のないURLやリダイレクトするURLでも、バイト列がサポートされている形式にデコードできれば問題ありません。HTTPリダイレクトは追跡されます。EXIFの向き情報は正規化されるため、回転した状態のスマートフォン写真も見た目通りに使用されます。

    制限: 各辺が最低 32 ピクセル、合計で最大 178,956,970 ピクセル、ダウンロード後で最大 20,000,000 バイトです。data URIの場合、この制限はデコード後のバイト数に適用されるため、元のファイル自体はそのサイズまで使用できます — base64テキストはおよそ3分の1大きくなりますが、それはリクエストボディのサイズに関係する話であり、この制限には関係しません。data URIは image/* のcontent typeと ;base64 を宣言する必要があります。

    画像を指定する方法は2つあります:

    • パブリックにアクセス可能なURL: パブリックインターネットからアクセス可能なURL。
    • Data URI: 画像のbase64エンコードされたdata URI。data URIの例: data:image/jpeg;base64,<your base64-encoded image data>
  • Name
    name
    Type
    string
    Description

    表示用の任意のタスク名です。最大100文字。

  • Name
    remove_background
    Type
    boolean
    デフォルト false
    Description

    true に設定すると、image_urls で返される表示用レンダーは、背景が除去された透明RGBA PNGとなり、任意の背景に合成できます。

    これは表示用レンダーにのみ適用されます。buildエンドポイントが使用する候補には影響しないため、3Dの結果はどちらの場合でも同一です。

戻り値

レスポンスの result プロパティには、新しく作成されたキーキャッププロトタイプタスクのタスク id が含まれます。Get a Task エンドポイントをポーリングするか、またはstreamをサブスクライブして、タスクが SUCCEEDED に達するまで待ち、その後 candidate_ids からエントリを取得し、タスクIDとともにbuildエンドポイントに渡してください。

失敗モード

  • Name
    400 - Bad Request
    Description

    リクエストが受け入れられませんでした。よくある原因:

    • パラメータ不足: image_url は必須です。
    • 無効な画像形式: 指定された image_url がサポートされている形式(.jpg.jpeg.png.webp)ではありません。
    • 画像サイズが範囲外: 画像が小さすぎる、最大ファイルサイズを超えている、または最大ピクセル数を超えています。
    • 到達不能なURL: image_url をダウンロードできませんでした(404またはtimeout)。
    • 無効なData URI: base64文字列の形式が不正です。
    • コンテンツがフラグ付けされた: 入力画像がNSFW moderationによってフラグ付けされました。
  • Name
    401 - Unauthorized
    Description

    認証に失敗しました。APIキーを確認してください。

  • Name
    402 - Payment Required
    Description

    アカウントが無料プランである(タスクの作成には有料プランが必要です)か、クレジットが不足しています。

  • Name
    403 - Forbidden
    Description

    入力画像が知的財産moderationによってフラグ付けされました。

  • Name
    429 - Too Many Requests
    Description

    レート制限を超えました。

  • Name
    500 - Internal Server Error
    Description

    予期しないサーバー側のエラーが発生しました — 例えばcontent-moderationサービスが利用できなかった、入力画像のステージングに失敗した、またはタスクを作成できなかった場合です。この場合タスクは作成されないため、再試行しても安全です。

Request

POST
/openapi/creative-lab/keycap/v1/prototype
# Stage 1: generate a finished-keycap design render
curl https://api.meshy.ai/openapi/creative-lab/keycap/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>"
  }'

Response

{
  "result": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef"
}

POST/openapi/creative-lab/keycap/v1/build

キーキャップビルドタスクを作成する

成功したプロトタイプタスクとそのキャンディデートの1つから、最終的なテクスチャ付きの3Dキーキャップモデルを生成します。単一のビルドタスクは、パイプライン全体をエンドツーエンドで実行します——選択したデザインからのホワイトモデル生成、キャリブレーション済みのデフォルトポーズを使用したキーキャップベースへの自動的な位置合わせとカット(インタラクティブな調整は不要)、モデル全体のカラーリング、そして最終的な組み立てとエクスポートです。ビルドには通常3〜7分かかり、複数のビルドが同時に実行されている場合は上限に近くなります。 レスポンスの形式についてはキーキャップビルドタスクオブジェクトを参照してください。

パラメータ

  • Name
    input_task_id
    Type
    string
    必須
    Description

    この同じOpenAPIエンドポイント経由で作成されたプロトタイプタスクのタスクIDです。プロトタイプは同じMeshyアカウントによって作成されている必要があり、SUCCEEDEDに到達している必要があり、少なくとも1つのキャンディデートを生成している必要があります。

    webapp経由で作成されたプロトタイプタスクは受け付けられません——buildエンドポイントはPOST /openapi/creative-lab/keycap/v1/prototypeによって生成されたプロトタイプタスクのみを受け付け、他のソースはすべて404で拒否します。

  • Name
    candidate_id
    Type
    string
    必須
    Description

    ビルド対象のキャンディデートで、成功したプロトタイプタスクのcandidate_ids配列から取得します。そのタスクに属している必要があり、それ以外の値は400で拒否されます。

  • Name
    name
    Type
    string
    Description

    表示用の任意のタスク名です。最大100文字です。

options

任意のジオメトリ調整です。すべてのフィールドにキャリブレーション済みのデフォルト値があります——上書きしたいものだけを送信してください。

  • Name
    base_model
    Type
    string
    デフォルト cherry-mx-1x1-r1
    Description

    ビルド対象のキーキャップベースです。現在利用可能な値はcherry-mx-1x1-r1(標準のCherry MXプロファイル1uキーキャップ)のみです。3〜5個の追加の主流な標準サイズが計画されていますが、カスタムサイズはサポートされていません。

  • Name
    head_size_mm
    Type
    number
    デフォルト 23
    Description

    スカルプトされたヘッドの目標サイズ(ミリメートル単位)です。その最長寸法がこの値にスケーリングされます。範囲: [10, 40]。おおよそ32.9を超える値は、ヘッドがベースの保護フットプリント制限に収まるように縮小される場合があるため、実際に提供される最長寸法はリクエストした値より小さくなることがあります。適用された値は現在タスクオブジェクトに反映されません——実際に受け取ったサイズを確認する必要がある場合は、ダウンロードしたモデル内のkeycap-headメッシュのバウンディングボックスを測定してください。

  • Name
    vertical_offset_mm
    Type
    number
    デフォルト 0
    Description

    ヘッドをベースに配置する前に適用される垂直方向のオフセット(ミリメートル単位)です。範囲: [-5, 5]

戻り値

レスポンスのresultプロパティには、新しく作成されたキーキャップビルドタスクのタスクidが含まれます。タスクを取得するエンドポイントをポーリングするか、ストリームをサブスクライブして、タスクがSUCCEEDEDに到達するまで待ち、その後model_urls.glbmodel_urls.obj_zipからアーティファクトをダウンロードしてください。

失敗モード

  • Name
    400 - Bad Request
    Description

    リクエストが受け付けられませんでした。よくある原因:

    • パラメータの欠落: input_task_idcandidate_idは必須です。
    • 無効なUUID: input_task_idが有効なUUIDではありません。
    • 親タスクが未完了: 参照されているプロトタイプタスクがまだSUCCEEDEDに到達していません。
    • キャンディデートが存在しない: プロトタイプタスクは成功しましたが、キャンディデートを生成しませんでした。
    • 不明なキャンディデート: candidate_idが入力タスクのキャンディデートのいずれでもありません。
    • オプションが範囲外: optionsフィールドのいずれかが許可された範囲または列挙セットの外にありました。
  • Name
    401 - Unauthorized
    Description

    認証に失敗しました。APIキーを確認してください。

  • Name
    402 - Payment Required
    Description

    アカウントが無料プランである(タスクの作成には有料プランが必要です)か、クレジットが不足しています。

  • Name
    404 - Not Found
    Description

    参照されているプロトタイプタスクが存在しない、別のユーザーに属している、またはwebapp経由で作成されたものです(APIモードのプロトタイプタスクのみがビルドに連鎖できます)。

  • Name
    429 - Too Many Requests
    Description

    レート制限を超えました。

  • Name
    500 - Internal Server Error
    Description

    予期しないサーバー側のエラーが発生しました——例えば、コンテンツmoderationサービスが利用できなかった、入力画像のステージングに失敗した、またはタスクを作成できなかった場合です。この場合タスクは作成されないため、再試行しても安全です。

Request

POST
/openapi/creative-lab/keycap/v1/build
# Stage 2: build the chosen candidate into a 3D keycap
curl https://api.meshy.ai/openapi/creative-lab/keycap/v1/build \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "input_task_id": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef",
    "candidate_id": "0198c1b2-33f5-7d21-a4b7-8e9d0c1f2a3b",
    "options": {
      "base_model": "cherry-mx-1x1-r1",
      "head_size_mm": 23,
      "vertical_offset_mm": 0
    }
  }'

Response

{
  "result": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af"
}

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

キーキャップタスクの取得

有効なタスク id を指定して、プロトタイプまたはビルドタスクを取得します。URL パスは タスクのステージと一致している必要があります — /prototype/:id を通じて取得された ビルドタスクは 404 を返し、その逆も同様です。

レスポンスの形式については、キーキャッププロトタイプタスクオブジェクト および キーキャップビルドタスクオブジェクト を参照してください。

パラメーター

  • Name
    id
    Type
    path
    Description

    取得するキーキャップタスクの一意の識別子。

戻り値

レスポンスにはキーキャップタスクオブジェクトが含まれます。その形式は、 どのステージがリクエストされたかによって異なります。

Request

GET
/openapi/creative-lab/keycap/v1/prototype/019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef
# Prototype
curl https://api.meshy.ai/openapi/creative-lab/keycap/v1/prototype/019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef \
  -H "Authorization: Bearer ${YOUR_API_KEY}"

# Build
curl https://api.meshy.ai/openapi/creative-lab/keycap/v1/build/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af \
  -H "Authorization: Bearer ${YOUR_API_KEY}"

Prototype Response

{
  "id": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef",
  "type": "creative-lab-keycap-prototype",
  "name": "",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142456000,
  "started_at": 1753142460000,
  "finished_at": 1753142516000,
  "expires_at": 1753401716000,
  "preceding_tasks": 0,
  "task_error": null,
  "consumed_credits": 12,
  "image_urls": [
    "https://assets.meshy.ai/***/design-1.png?Expires=***"
  ],
  "candidate_ids": [
    "0198c1b2-33f5-7d21-a4b7-8e9d0c1f2a3b"
  ]
}

Build Response

{
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "type": "creative-lab-keycap-build",
  "name": "",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142600000,
  "started_at": 1753142610000,
  "finished_at": 1753143050000,
  "expires_at": 1753402250000,
  "preceding_tasks": 0,
  "task_error": null,
  "consumed_credits": 50,
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model.glb?Expires=***",
    "obj_zip": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model-obj.zip?Expires=***"
  },
  "process_image_urls": {
    "head_design": "https://assets.meshy.ai/***/head-design.png?Expires=***",
    "composite": "https://assets.meshy.ai/***/composite.png?Expires=***",
    "base_canvas": "https://assets.meshy.ai/***/base-canvas.png?Expires=***"
  }
}

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

Keycapタスクを削除する

keycapタスクをキャンセルします。タスクがまだ PENDING の場合、作成時に 消費されたクレジットは返金されます。すでに IN_PROGRESS のタスクは返金なしでキャンセルされます(ワーカーがすでに リソースを消費している可能性があるため)。すでに終端状態 (SUCCEEDEDFAILEDCANCELED)に達しているタスクはキャンセルできません。

URLパスはタスクのステージと一致する必要があります。/prototype/:buildId に対する DELETE404 を返します。

パスパラメーター

  • Name
    id
    Type
    path
    Description

    キャンセルするkeycapタスクの一意の識別子。

戻り値

成功時は空のボディで 204 No Content を返します。

失敗モード

  • Name
    400 - Bad Request
    Description

    タスクはすでに終端状態にあり、キャンセルできません。

  • Name
    404 - Not Found
    Description

    タスクが存在しない、別のユーザーに属している、またはそのステージがURLパスと一致しません。

  • Name
    500 - Internal Server Error
    Description

    キャンセル中に予期しないサーバー側のエラーが発生しました。タスクがキャンセルされたかどうかは不明です。再試行する前に読み直して確認してください。

Request

DELETE
/openapi/creative-lab/keycap/v1/prototype/019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef
curl --request DELETE \
  --url https://api.meshy.ai/openapi/creative-lab/keycap/v1/prototype/019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef \
  -H "Authorization: Bearer ${YOUR_API_KEY}"

Response

// Returns 204 No Content on success (empty body).

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

Stream a Keycap Task

Server-Sent Events(SSE)を介して、キーキャップタスクのリアルタイム更新をストリーミングします。 URLパスはタスクのステージと一致している必要があります。/prototype/:buildId/stream でストリームを開くと、status_code: 404 を含む単一の event: error ペイロードが送出され、ストリームは閉じられます。

パラメータ

  • Name
    id
    Type
    path
    Description

    ストリーミング対象のキーキャップタスクを識別する一意のIDです。

レスポンス

Keycap Prototype または Keycap Build タスクオブジェクトのストリームを Server-Sent Eventsとして返します。各フレームには、そのステージの完全なタスクオブジェクトが含まれます — Getエンドポイントが返すものと同じ形式です — そのため、タスクが PENDING または IN_PROGRESS の間は、 出力フィールドはまだ値が入っておらず(null[]、または {})、finished_atnull になります。

Request

GET
/openapi/creative-lab/keycap/v1/build/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/stream
curl -N https://api.meshy.ai/openapi/creative-lab/keycap/v1/build/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/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; fields not yet populated are null / empty.
// The PENDING frame below is abbreviated to the fields that change.
event: message
data: {
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "progress": 0,
  "status": "PENDING"
}

event: message
data: {
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "type": "creative-lab-keycap-build",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142600000,
  "started_at": 1753142610000,
  "finished_at": 1753143050000,
  "expires_at": 1753402250000,
  "task_error": null,
  "consumed_credits": 50,
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model.glb?Expires=***",
    "obj_zip": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model-obj.zip?Expires=***"
  },
  "process_image_urls": {
    "head_design": "https://assets.meshy.ai/***/head-design.png?Expires=***"
  }
}

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

キーキャップタスク一覧の取得

単一のステージにおけるキーキャップタスクのページネーションされたリストを取得します。URL パスがステージを選択します — /prototype はプロトタイプタスクを返し、/build はビルドタスクを返します。もう一方のステージのタスクは、いずれのレスポンスにも含まれません。

パスパラメーター

  • Name
    stage
    Type
    path
    必須
    Description

    prototype または build のいずれかです。このコレクションは、URL に一致するステージのタスクのみを返します — /prototype を取得してもビルドタスクが返されることはなく、その逆も同様です。

クエリパラメーター

  • 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 を一覧表示する場合は キーキャッププロトタイプタスクオブジェクト/build を一覧表示する場合は キーキャップビルドタスクオブジェクト となります。

Request

GET
/openapi/creative-lab/keycap/v1/prototype
# List prototype tasks
curl https://api.meshy.ai/openapi/creative-lab/keycap/v1/prototype?page_size=10 \
  -H "Authorization: Bearer ${YOUR_API_KEY}"

# List build tasks
curl https://api.meshy.ai/openapi/creative-lab/keycap/v1/build?page_size=10 \
  -H "Authorization: Bearer ${YOUR_API_KEY}"

Response (List Prototype Tasks)

[
  {
    "id": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef",
    "type": "creative-lab-keycap-prototype",
    "name": "",
    "status": "SUCCEEDED",
    "progress": 100,
    "created_at": 1753142456000,
    "started_at": 1753142460000,
    "finished_at": 1753142516000,
    "expires_at": 1753401716000,
    "preceding_tasks": 0,
    "task_error": null,
    "consumed_credits": 12,
    "image_urls": [
      "https://assets.meshy.ai/***/design-1.png?Expires=***"
    ],
    "candidate_ids": [
      "0198c1b2-33f5-7d21-a4b7-8e9d0c1f2a3b"
    ]
  }
]

The Keycap Prototype Task Object

Keycap Prototype Taskオブジェクトは、Meshyが元の写真から完成済みキーキャップデザイン画像を1つ生成するために管理する作業単位です。このステージの出力は、input_task_idcandidate_idを介してビルドステージに連結されます。

プロパティ

  • Name
    id
    Type
    string
    Description

    タスクの一意の識別子です。実装の詳細としてタスクIDにはk-sortable UUIDを使用していますが、このidの形式についていかなる前提も置かないようにしてください。

  • Name
    type
    Type
    string
    Description

    タスクの種類です。値はcreative-lab-keycap-prototypeです。

  • Name
    name
    Type
    string
    Description

    タスク作成時に指定されたタスク名です。名前が指定されなかった場合は空文字列になります。

  • Name
    status
    Type
    string
    Description

    タスクのステータスです。取り得る値はPENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELEDのいずれかです。

  • Name
    progress
    Type
    integer
    Description

    タスクのprogressです。タスクがまだ開始されていない場合、このプロパティは0になります。タスクが成功すると、100になります。

  • Name
    created_at
    Type
    timestamp
    Description

    タスクが作成された時刻のタイムスタンプ(ミリ秒単位)です。

  • Name
    started_at
    Type
    timestamp
    Description

    タスクが開始された時刻のタイムスタンプ(ミリ秒単位)です。タスクがまだ開始されていない場合、このプロパティは0になります。

  • Name
    finished_at
    Type
    timestamp
    Description

    タスクが終了した時刻のタイムスタンプ(ミリ秒単位)です。タスクがまだ終了していない場合、このプロパティは0になります。

  • Name
    expires_at
    Type
    timestamp
    Description

    タスクの結果が失効する時刻のタイムスタンプ(ミリ秒単位)です。

  • Name
    preceding_tasks
    Type
    integer
    Description

    先行するタスクの数です。

  • Name
    task_error
    Type
    object
    Description

    失敗したタスクのエラー詳細です。task_errorオブジェクトの完全なリファレンスについては、エラーを参照してください。

  • Name
    consumed_credits
    Type
    integer
    Description

    このタスクによって消費されたクレジットの数です。SUCCEEDEDに達したタスクは、そのステージの全額が課金されます。作成されなかったタスク(リクエスト時の4xx、moderationによる拒否を含む)は一切課金されません。FAILEDに達したタスクは0を返します——非同期のmoderationブロックを含め、課金分は返金されます。DELETEによるキャンセルは、タスクがまだPENDINGの間のみ返金されます。すでにIN_PROGRESSのタスクは、作業が既に費やされているため課金されたままになります。

  • Name
    image_urls
    Type
    array of strings
    Description

    完成済みキーキャップデザインのレンダリング画像——候補が完成キーキャップとしてどのように見えるかをダウンロードできるURLです。1件のエントリのみを保持します。image_urls[i]candidate_ids[i]に対応します。タスクがSUCCEEDEDに達するまでは空です。このURLは表示のみを目的としており、ビルドエンドポイントはこれらのURLではなくcandidate_idsを消費します。model_urlsと同じURLのライフサイクル、つまり署名付きで、Authorizationヘッダーは不要、expires_atまで有効、タスクを再読み込みしても安定しています。

  • Name
    candidate_ids
    Type
    array of strings
    Description

    image_urlsと並行する、不透明な候補識別子です。選択したデザインに対応するエントリを、ビルドリクエストのcandidate_idとして渡してください。これらのidの形式についていかなる前提も置かないようにしてください。

Example Keycap Prototype Task Object

{
  "id": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef",
  "type": "creative-lab-keycap-prototype",
  "name": "",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142456000,
  "started_at": 1753142460000,
  "finished_at": 1753142516000,
  "expires_at": 1753401716000,
  "preceding_tasks": 0,
  "task_error": null,
  "consumed_credits": 12,
  "image_urls": [
    "https://assets.meshy.ai/***/design-1.png?Expires=***"
  ],
  "candidate_ids": [
    "0198c1b2-33f5-7d21-a4b7-8e9d0c1f2a3b"
  ]
}

Keycap Build Taskオブジェクト

Keycap Build Taskオブジェクトは、成功したプロトタイプタスクと選択されたキャンディデートから、最終的なテクスチャ付き3Dキーキャップを生成するためにMeshyが追跡する作業単位です。1回のビルドで、ホワイトモデル生成、自動シーティング&カッティング、カラーリング、アセンブリ、エクスポートというフルパイプラインが実行されます。

プロパティ

  • Name
    id
    Type
    string
    Description

    タスクの一意な識別子。

  • Name
    type
    Type
    string
    Description

    タスクの種類。値は creative-lab-keycap-build です。

  • Name
    name
    Type
    string
    Description

    タスク作成時に指定されたタスク名。名前が指定されなかった場合は空文字列になります。

  • Name
    status
    Type
    string
    Description

    タスクのステータス。可能な値は PENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELED のいずれかです。

  • Name
    progress
    Type
    integer
    Description

    タスクのprogress。タスクがまだ開始されていない場合、このプロパティは 0 になります。タスクが成功すると 100 になります。

  • Name
    created_at
    Type
    timestamp
    Description

    タスクが作成されたときのタイムスタンプ(ミリ秒単位)。

  • Name
    started_at
    Type
    timestamp
    Description

    タスクが開始されたときのタイムスタンプ(ミリ秒単位)。

  • Name
    finished_at
    Type
    timestamp
    Description

    タスクが終了したときのタイムスタンプ(ミリ秒単位)。

  • Name
    expires_at
    Type
    timestamp
    Description

    タスク結果が期限切れになるときのタイムスタンプ(ミリ秒単位)。

  • Name
    preceding_tasks
    Type
    integer
    Description

    先行タスクの数。ステータスが PENDING のときのみ意味を持ちます。

  • Name
    task_error
    Type
    object
    Description

    失敗したタスクのエラー詳細。task_error オブジェクトの完全なリファレンスについては、エラーを参照してください。

  • Name
    consumed_credits
    Type
    integer
    Description

    このタスクによって消費されたクレジット数。SUCCEEDED に達したタスクは、そのステージの全額が課金されます。作成されなかったタスク(リクエスト時の 4xx、moderationによる拒否を含む)は一切課金されません。FAILED に達したタスクは 0 を返します — 非同期のmoderationブロックを含め、課金は返金されます。DELETE によるキャンセルは、タスクがまだ PENDING の間のみ返金されます。すでに IN_PROGRESS になっているタスクは、作業が消費されているため課金されたままです。

  • Name
    model_urls
    Type
    object
    Description

    生成されたモデルアーティファクトのダウンロード可能なURL。GLBとOBJバンドルはいずれも実世界のミリメートル単位Y-upでエクスポートされ、キーキャップの前面は+Zを向きます。メッシュは keycap-headkeycap-base という名前になります。ベースがパターン塗りにフォールバックした場合、ステムの空洞用に3番目のメッシュ keycap-base-interior も存在します。メッシュが必ず2つだけであると仮定しないでください。

    これらは署名付きURLです。Authorization ヘッダーを付けずに取得してください。これらは expires_at まで有効であり、これは finished_at から3日後です。この期間内にタスクを再読み込みしても、新たに署名されたURLではなく同一のURLが返されます。期限が切れる前に、必ず自分でファイルをダウンロードして保存してください。期限切れのリンクを更新する方法はありません。

    • Name
      glb
      Type
      string
      Description

      最終的なテクスチャ付き model.glb のダウンロード可能なURL。

    • Name
      obj_zip
      Type
      string
      Description

      model.objmodel.mtl、およびそのMTLが実際に参照しているテクスチャPNGを含むzipバンドルへのダウンロード可能なURL。単色のベースでは keycap-head.png のみが提供されます。パターン付きのベースでは keycap-base.png も提供されます。

  • Name
    process_image_urls
    Type
    object
    Description

    中間プロセス画像のダウンロード可能なURLで、種類をキーとしています。model_urls と同じURLライフサイクルです:署名付きで、Authorization ヘッダーは不要、expires_at まで有効、タスクを再読み込みしても安定しています。現在発行される種類は以下の通りです:

    • head_design — ビルドが使用した、選択されたキャンディデートのデザイン画像(常に存在します)。
    • composite — 選択されたキャンディデートの完成キーキャップ表示レンダー(利用可能な場合に存在します)。
    • base_canvas — 描画されたキーキャップベースのキャンバス(利用可能な場合に存在します)。

    このキーセットは今後拡張される可能性があるものとして扱ってください。新しい種類が破壊的変更なしに追加される可能性があります。

Example Keycap Build Task Object

{
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "type": "creative-lab-keycap-build",
  "name": "",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142600000,
  "started_at": 1753142610000,
  "finished_at": 1753143050000,
  "expires_at": 1753402250000,
  "preceding_tasks": 0,
  "task_error": null,
  "consumed_credits": 50,
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model.glb?Expires=***",
    "obj_zip": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model-obj.zip?Expires=***"
  },
  "process_image_urls": {
    "head_design": "https://assets.meshy.ai/***/head-design.png?Expires=***",
    "composite": "https://assets.meshy.ai/***/composite.png?Expires=***",
    "base_canvas": "https://assets.meshy.ai/***/base-canvas.png?Expires=***"
  }
}

エンドツーエンドの例

完全なフローは次のとおりです。写真からプロトタイプを作成し、SUCCEEDEDになるまでポーリングし、candidate_idsから候補を1つ選び、その候補でビルドを作成し、ビルドがSUCCEEDEDになるまでポーリングしてから、model_urlsからGLBとOBJバンドルをダウンロードします。

この例ではプログラム的に最初の候補を選択しています。実際の統合では、image_urlsのエントリをエンドユーザーに表示して選ばせることになるでしょう。選択されたインデックスはcandidate_idsに1対1で対応します。

Complete flow

POST
/openapi/creative-lab/keycap/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://...
: "${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

BASE="https://api.meshy.ai/openapi/creative-lab/keycap/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 '{"image_url":"data:%s;base64,' "$MIME"
    base64 <"$IMAGE_PATH" | tr -d '\n'
    printf '"}'
  } >"$BODY"
else
  printf '{"image_url":"%s"}' "$IMAGE_URL" >"$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 design render
poll prototype "$PROTO_ID"

# 3. Pick a candidate (first one here; show image_urls to a user in production)
CANDIDATE_ID=$(api GET "$BASE/prototype/$PROTO_ID" | jq -r '.candidate_ids[0]')

# 4. Create the build task
jq -n --arg p "$PROTO_ID" --arg c "$CANDIDATE_ID" \
  '{input_task_id: $p, candidate_id: $c}' >"$BODY"
BUILD_ID=$(api POST "$BASE/build" \
  -H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')

# 5. Wait for the model (a build usually takes 3-7 minutes)
poll build "$BUILD_ID"

# 6. Download the artifacts. These are signed URLs: no Authorization header,
#    and they stay valid for 3 days after the task finishes.
TASK=$(api GET "$BASE/build/$BUILD_ID")
curl --silent --show-error --fail --max-time 900 \
  -o keycap.glb "$(jq -r '.model_urls.glb' <<<"$TASK")"
curl --silent --show-error --fail --max-time 900 \
  -o keycap-obj.zip "$(jq -r '.model_urls.obj_zip' <<<"$TASK")"
echo "Done: keycap.glb + keycap-obj.zip"