Creative Lab 키캡 API
사진을 두 단계에 걸쳐 기계식 키보드용 풀컬러 커스텀 키캡으로 변환합니다. 프로토타입 작업은 사진으로부터 완성된 키캡의 이미지를 생성합니다. 빌드 작업은 해당 이미지를 텍스처가 적용된 3D 키캡 모델로 변환합니다. 이때 프로토타입 작업의 ID를 input_task_id로, 이미지의 후보 ID를 candidate_id로 사용합니다.
POST /openapi/creative-lab/keycap/v1/prototypePOST /openapi/creative-lab/keycap/v1/build
두 POST endpoint 모두 유료 플랜이 필요합니다. 무료 플랜 계정의 요청은 402를 반환합니다.
Keycap 프로토타입 작업 생성
사진으로부터 완성된 키캡의 이미지 하나를 생성합니다. 작업의 image_urls에 이미지가 담기고, candidate_ids에 해당 ID가 담기며, 각각 하나의 항목이 들어 있습니다. 디자인이 마음에 들지 않으면 다른 프로토타입 작업을 생성하세요. Meshy는 각 프로토타입 작업에 대해 별도로 과금합니다.
3D 키캡을 빌드하려면 이 작업의 ID를 input_task_id로 빌드 엔드포인트에 전달하고, candidate_ids 항목을 candidate_id로 전달하세요. 작업의 필드에 대해서는 Keycap 프로토타입 작업 객체를 참고하세요.
Request
# 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"
}
매개변수
- Name
- image_url
- Type
- string
- 필수
- Description
키캡 디자인으로 변환할 사진으로, 공개 URL 또는 data URI(
data:image/jpeg;base64,<your base64-encoded image data>) 형식입니다.이미지는 최대 20MB(20,000,000바이트)의 JPG, JPEG, PNG, 또는 WebP 파일이어야 합니다. 각 변은 최소 32픽셀이어야 하며, 이미지는 총 178,956,970픽셀을 초과할 수 없습니다. 이 제한을 벗어나는 이미지는
400을 반환합니다.Meshy는 URL의 파일 확장자가 아니라 이미지 데이터로부터 형식을 감지합니다. 확장자가 없는 URL도 동작하며, Meshy는 HTTP 리디렉션을 따라갑니다. Meshy는 EXIF 방향 정보를 적용하므로, 회전된 휴대폰 사진도 보이는 그대로 나옵니다.
data URI는
data:image/png;base64,...와 같이 이미지 타입과 함께 base64로 인코딩되어야 하며, 디코딩된 이미지는 JPEG, PNG, 또는 WebP여야 합니다. 20MB 제한은 디코딩된 이미지에 적용되므로, base64 텍스트는 그보다 약 3분의 1 더 클 수 있습니다.
- Name
- name
- Type
- string
- Description
작업의 이름으로, 최대 100자까지 가능합니다. 작업의
name필드에 그대로 반환됩니다. 더 긴 이름은400을 반환합니다.
- Name
- remove_background
- Type
- boolean
- 기본값 false
- Description
프로토타입 이미지에서 배경을 제거할지 여부입니다.
true이면 투명한 RGBA PNG가 반환되므로, 키캡을 어떤 배경 위에도 배치할 수 있습니다. Meshy가 배경을 제거할 수 없는 경우, 배경이 있는 이미지를 그대로 반환하며, 이 경우에도 작업은 성공합니다.빌드가 3D로 변환하는 헤드 디자인은 어느 경우든 배경을 유지합니다. 빌드는
image_urls의 이미지로부터 키캡 베이스를 칠하며,true를 전송한 경우 배경 없이 칠합니다. 빌드는 해당 이미지를process_image_urls.composite로 반환합니다.
반환 값
result 필드에는 새 프로토타입 작업의 ID가 담깁니다. status가 SUCCEEDED가 될 때까지 작업을 가져오거나 스트리밍하세요. 그런 다음 해당 ID를 input_task_id로 빌드 엔드포인트에 전달하고, candidate_ids의 항목을 candidate_id로 전달하세요.
실패 모드
- Name
400 - Bad Request- Description
요청을 실행할 수 없습니다. 예를 들면 다음과 같습니다:
image_url이 누락됨.- 이미지가 JPG, JPEG, PNG, 또는 WebP 파일이 아님.
- 이미지가 너무 작거나, 20MB를 초과하거나, 최대 픽셀 수를 초과함.
- Meshy가 이미지를 다운로드할 수 없음, 예를 들어 URL이
404를 반환하거나 시간 초과됨. - data URI가 유효한 base64가 아님.
- 이미지가 NSFW로 플래그됨.
오류 메시지는 어떤 문제가 발견되었는지 알려줍니다. 요청을 수정한 뒤 다시 전송하세요.
- Name
401 - Unauthorized- Description
API 키가 없거나 유효하지 않습니다.
Authorization헤더를 확인하세요.
- Name
402 - Payment Required- Description
다음 중 하나에 해당합니다:
- 계정에 크레딧이 충분하지 않음.
- API 키, 작업 공간, 또는 구성원이 크레딧 한도에 도달함.
- 계정이 무료 플랜을 사용 중임.
크레딧과 플랜을 확인한 뒤 다시 시도하세요.
- Name
403 - Forbidden- Description
팀의 IP 필터링이 켜져 있고, Meshy가 해당 이미지를 제3자 지식재산권 문제로 플래그했습니다. 사용 권한이 있는 이미지를 전송하세요.
- Name
429 - Too Many Requests- Description
다음 제한 중 하나에 도달했습니다:
- 속도 제한을 초과하는 요청을 전송했습니다. 몇 초 기다린 뒤 다시 시도하세요. 속도 제한을 참고하세요.
- 대기 중이거나 실행 중인 작업이 너무 많습니다. 일부가 끝날 때까지 기다린 뒤 다시 시도하세요.
- 크레딧이 남아 있지 않은 무제한 플랜에서, 크레딧 없이 실행할 수 있는 작업 수에 도달했습니다. 작업이 끝날 때까지 기다리거나 크레딧을 추가하세요.
- Name
500 - Internal Server Error- Description
Meshy에서 서버 오류가 발생했습니다. 예를 들어 콘텐츠 moderation이나 지식재산권 확인을 실행할 수 없었거나, Meshy가 이미지를 저장할 수 없었습니다. Meshy는 작업을 생성하지 않으며, 청구된 크레딧이 있다면 환불합니다. 요청을 다시 시도하세요.
키캡 빌드 작업 생성
성공한 프로토타입 작업과 그 후보 중 하나로부터 텍스처가 적용된 3D 키캡을 생성합니다. 필드에 대한 자세한 내용은 Keycap build 작업 객체를 참조하세요.
하나의 빌드 작업이 모든 단계를 실행합니다. 디자인으로부터 3D 모델을 생성하고 색상을 입힙니다. 그런 다음 보정된 기본 포즈로 모델을 키캡 베이스에 안착시키고 재단하므로, 수동으로 조정할 필요가 없습니다. 마지막으로 키캡을 조립하고 파일을 내보냅니다. 빌드는 일반적으로 3~7분이 걸립니다.
Request
# 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"
}
매개변수
- Name
- input_task_id
- Type
- string
- 필수
- Description
빌드할 프로토타입 작업의 ID입니다. 이 값은
POST /openapi/creative-lab/keycap/v1/prototype으로 귀하의 계정이 생성했으며 상태가SUCCEEDED인 작업이어야 합니다.API를 통해 생성된 귀하의 Keycap 프로토타입 작업이 아닌 ID는
404를 반환하며, 웹 앱에서 만든 프로토타입도 마찬가지입니다.
- Name
- candidate_id
- Type
- string
- 필수
- Description
프로토타입 작업의
candidate_ids배열에서 빌드할 후보입니다. 해당 배열에 없는 값은400을 반환합니다.
- Name
- name
- Type
- string
- Description
작업의 이름으로, 최대 100자까지 가능합니다. 작업의
name필드로 반환됩니다. 더 긴 이름은400을 반환합니다.
options
선택적 지오메트리 설정입니다. 각 필드에는 보정된 기본값이 있으므로, 변경하려는 필드만 보내면 됩니다.
- Name
- base_model
- Type
- string
- 기본값 cherry-mx-1x1-r1
- Description
빌드할 키캡 베이스입니다. 유일한 값은 표준 Cherry MX 프로파일 1u 키캡인
cherry-mx-1x1-r1입니다. 커스텀 크기는 지원되지 않으며, 다른 값을 보내면400을 반환합니다.
- Name
- head_size_mm
- Type
- number
- 기본값 23
- Description
가장 긴 치수를 기준으로 한 헤드의 크기로, 밀리미터 단위이며
10부터40까지입니다. Meshy는 가장 긴 치수가 이 값과 일치하도록 헤드의 크기를 조정합니다. 범위를 벗어난 값은400을 반환합니다.약
32.9를 초과하는 값의 경우, Meshy는 헤드가 베이스의 보호 영역 한도 내에 들어가도록 크기를 줄일 수 있습니다. 이 경우 헤드가 요청한 것보다 더 작게 나올 수 있습니다. 작업 객체는 Meshy가 적용한 크기를 반환하지 않습니다. 이를 확인하려면 모델에서keycap-head메시의 바운딩 박스를 측정하세요.
- Name
- vertical_offset_mm
- Type
- number
- 기본값 0
- Description
Meshy가 헤드를 베이스에 안착시키기 전에 적용할 수직 오프셋으로, 밀리미터 단위이며
-5부터5까지입니다. 범위를 벗어난 값은400을 반환합니다.
반환값
result 필드에는 새 빌드 작업의 ID가 담깁니다. status가 SUCCEEDED가 될 때까지 작업을 가져오거나 스트리밍하세요. 그런 다음 model_urls.glb에서 GLB 파일을, model_urls.obj_zip에서 OBJ 번들을 다운로드하세요.
Meshy는 GLB 파일과 OBJ 번들을 밀리미터 단위의 실제 크기로 내보냅니다. 두 파일 모두 Y축이 위를 향하는 좌표계를 사용하며, 키캡의 앞면은 +Z를 향합니다.
실패 모드
- Name
400 - Bad Request- Description
요청을 실행할 수 없습니다. 예를 들어:
input_task_id가 누락되었거나 유효한 작업 ID가 아닙니다.- 프로토타입 작업의 상태가
SUCCEEDED가 아닙니다. 아직 실행 중이라면 기다렸다가 다시 시도하세요. 실패했거나 취소된 경우, 새 프로토타입 작업을 생성하세요. - 프로토타입 작업은 성공했지만 후보가 없습니다. 새 프로토타입 작업을 생성하세요.
candidate_id가 누락되었거나, 프로토타입 작업의candidate_ids에 없습니다. 해당 배열의 값을 보내세요.options의 필드가 범위를 벗어났거나,base_model이 사용 가능한 값이 아닙니다.
오류 메시지에 어떤 문제가 발견되었는지 표시됩니다.
- Name
401 - Unauthorized- Description
API 키가 누락되었거나 유효하지 않습니다.
Authorization헤더를 확인하세요.
- Name
402 - Payment Required- Description
다음 중 하나에 해당합니다:
- 계정에 크레딧이 충분하지 않습니다.
- API 키, 작업 공간 또는 멤버가 크레딧 한도에 도달했습니다.
- 계정이 무료 플랜을 사용 중입니다.
크레딧과 플랜을 확인한 후 다시 시도하세요.
- Name
404 - Not Found- Description
input_task_id가 귀하의 계정이 API로 생성한 어떤 Keycap 프로토타입 작업과도 일치하지 않습니다. 웹 앱에서 만든 프로토타입도404를 반환합니다. 프로토타입 생성 응답에서 받은resultID를 보내세요.
- Name
429 - Too Many Requests- Description
다음 한도 중 하나에 도달했습니다:
- 속도 제한이 허용하는 것보다 더 많은 요청을 보냈습니다. 몇 초 기다렸다가 다시 시도하세요. 속도 제한을 참조하세요.
- 대기 중이거나 실행 중인 작업이 너무 많습니다. 일부가 완료될 때까지 기다렸다가 다시 시도하세요.
- 크레딧이 남아 있지 않은 무제한 플랜에서, 크레딧 없이 실행할 수 있는 작업 수에 도달했습니다. 작업이 완료되기를 기다리거나 크레딧을 추가하세요.
- Name
500 - Internal Server Error- Description
서버 오류로 인해 Meshy가 작업을 생성하지 못했습니다. Meshy는 청구된 크레딧을 환불합니다. 요청을 다시 시도하세요.
키캡 작업 조회
프로토타입 또는 빌드 작업을 반환합니다. 경로는 작업의 단계와 일치해야 합니다. /prototype/:id를 통해 요청한 빌드 작업은 404를 반환하며, /build/:id를 통해 요청한 프로토타입 작업도 마찬가지입니다.
필드에 대해서는 키캡 프로토타입 작업 객체와 키캡 빌드 작업 객체를 참조하세요.
Request
# 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=***"
}
}
매개변수
- Name
- id
- Type
- path
- Description
생성 응답에서 받은 작업 ID입니다.
반환값
경로의 단계와 일치하는 프로토타입 작업 객체 또는 빌드 작업 객체입니다.
실패 모드
- Name
400 - Bad Request- Description
id가 유효한 작업 ID가 아닙니다. 생성 응답의resultID를 전송하세요.
- Name
403 - Forbidden- Description
팀에서 IP Filtering이 켜져 있고, Meshy가 프로토타입 작업의 이미지를 제3자 지적 재산권 문제로 표시했습니다. 빌드 작업과 Enterprise 플랜의 팀은 이 오류가 발생하지 않습니다. 사용 권한이 있는 이미지로 프로토타입 작업을 생성하세요.
- Name
404 - Not Found- Description
이 ID를 가진 키캡 작업이 계정에 속해 있지 않거나, 작업의 단계가 경로와 일치하지 않습니다. ID를 확인하고 작업에 맞게
/prototype또는/build를 사용하세요.
- Name
500 - Internal Server Error- Description
Meshy가 지적 재산권 검사를 실행하지 못했습니다. 요청을 재시도하세요.
Keycap 작업 삭제
Keycap 작업을 취소합니다. PENDING 작업을 취소하면 해당 크레딧이 환불됩니다. IN_PROGRESS 작업은 이미 워커가 처리를 시작했기 때문에 환불 없이 취소됩니다. 최종 상태(SUCCEEDED, FAILED, 또는 CANCELED)에 있는 작업은 취소할 수 없습니다.
경로는 작업의 단계와 일치해야 합니다. 예를 들어, build 작업의 ID로 /prototype/:id에 DELETE를 요청하면 404가 반환됩니다.
Request
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).
경로 매개변수
- Name
- id
- Type
- path
- Description
취소할 작업의 ID입니다.
반환값
빈 본문과 함께 204 No Content를 반환합니다.
실패 모드
- Name
400 - Bad Request- Description
다음 중 하나에 해당합니다:
id가 유효한 작업 ID가 아닙니다. 생성 응답의resultID를 보내세요.- 작업이 이미 최종 상태(
SUCCEEDED,FAILED, 또는CANCELED)에 있어 취소할 수 없습니다.
- Name
404 - Not Found- Description
이 ID를 가진 Keycap 작업이 계정에 존재하지 않거나, 작업의 단계가 경로와 일치하지 않습니다. ID를 확인하고, 작업에 맞게
/prototype또는/build를 사용하세요.
- Name
500 - Internal Server Error- Description
작업을 취소하는 동안 Meshy에서 서버 오류가 발생하여 작업이 취소되었을 수도, 취소되지 않았을 수도 있습니다. 재시도하기 전에 작업을 조회하여
status를 확인하세요.
Keycap 작업 스트리밍
Keycap 작업의 업데이트를 Server-Sent Events (SSE)로 스트리밍합니다. 경로는 해당 작업의 단계와 일치해야 합니다. 일치하지 않으면, 예를 들어 build 작업의 ID로 /prototype/:id/stream에 요청하면, 스트림은 status_code: 404와 함께 하나의 error 이벤트를 전송하고 닫힙니다.
Request
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 following PENDING frame is shortened 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=***"
}
}
매개변수
- Name
- id
- Type
- path
- Description
생성 응답에서 제공된 작업 ID입니다.
반환값
prototype 또는 build 작업 객체의 스트림입니다. 각 이벤트는 Keycap 작업 조회가 반환하는 것과 동일한 전체 작업 객체를 포함합니다. 작업이 PENDING 또는 IN_PROGRESS 상태인 동안에는 출력 필드가 여전히 비어 있으며(null, [], 또는 {}), finished_at은 null입니다.
IP Filtering이 작업 결과를 차단하는 경우, 스트림은 그 자리에 get 요청이 반환했을 status_code와 함께 하나의 error 이벤트를 전송합니다.
키캡 작업 목록 조회
한 단계의 키캡 작업을 한 번에 한 페이지씩 반환합니다. 경로가 단계를 선택합니다. /prototype은 prototype 작업만 반환하고, /build는 build 작업만 반환합니다.
Request
# 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"
]
}
]
경로 매개변수
- Name
- stage
- Type
- path
- 필수
- Description
조회할 단계로,
prototype또는build입니다.
쿼리 매개변수
- Name
- page_num
- Type
- integer
- 기본값 1
- Description
반환할 페이지로,
1부터255까지입니다.0은 첫 페이지를 반환합니다.0에서255범위를 벗어난 값은400을 반환합니다.
- Name
- page_size
- Type
- integer
- 기본값 10
- Description
페이지당 작업 수로, 최대
100입니다.101에서255사이의 값은 100개의 작업을 반환하고,0은 기본값을 사용합니다.0에서255범위를 벗어난 값은400을 반환합니다.
- Name
- sort_by
- Type
- string
- 기본값 -created_at
- Description
정렬 순서입니다.
사용 가능한 값:
-created_at: 최신순+created_at: 오래된순
반환값
경로의 단계에 맞는 prototype 작업 객체 또는 build 작업 객체의 배열입니다.
키캡 프로토타입 작업 객체
프로토타입 작업은 사진으로부터 완성된 키캡 이미지 하나를 생성합니다. 디자인을 3D 키캡으로 변환하려면, 작업의 ID를 input_task_id로, 그 작업의 candidate_ids 항목을 candidate_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"
]
}
- Name
- id
- Type
- string
- Description
작업 ID입니다. 이 형식에 의존하지 마세요.
- Name
- type
- Type
- string
- Description
작업 유형으로, 항상
creative-lab-keycap-prototype입니다.
- Name
- name
- Type
- string
- Description
작업을 생성할 때 보낸
name이며, 보내지 않았다면""입니다.
- Name
- status
- Type
- string
- Description
작업의 상태입니다.
사용 가능한 값:
PENDING: 대기열에서 대기 중IN_PROGRESS: 결과 생성 중SUCCEEDED: 최종 상태이며, 결과 포함FAILED: 최종 상태이며,task_error에 사유 포함CANCELED: 최종 상태이며, 결과 없음
- Name
- progress
- Type
- integer
- Description
작업 완료율로,
0부터100까지입니다. 작업이 시작되기 전까지는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
작업 결과가 만료되는 시각으로, 유닉스 밀리초 단위입니다.
finished_at이후 3일이며, 작업이 완료되기 전까지는created_at이후 3일입니다. API 결과를 무기한 보관하는 Enterprise 계정의 경우 약 100년 후입니다. 에셋 보존을 참고하세요.
- Name
- preceding_tasks
- Type
- integer
- Description
작업이
PENDING상태일 때 대기열에서의 위치입니다.1은 다음 차례로 시작됨을 의미합니다. 작업이 대기열을 벗어나면0이 되며, 목록 결과에서는 항상0입니다.
- Name
- task_error
- Type
- object
- Description
작업이 실패한 이유입니다.
status가FAILED가 아니면null입니다. 오류를 참고하세요.
- Name
- consumed_credits
- Type
- integer
- Description
환불을 반영한 후, 작업에 청구된 크레딧 수입니다. 오류를 반환하는 요청은 청구되지 않습니다. 실패한 작업은 Meshy가 환불하므로
0입니다. 취소는 작업이PENDING상태일 때만 환불됩니다. Meshy가 청구 내역을 읽을 수 없는 경우, get 또는 stream 응답에서는 이 필드가 생략되며, list 요청은500을 반환합니다. 이 경우 요청을 재시도하세요.
- Name
- image_urls
- Type
- array of strings
- Description
완성된 키캡 이미지의 다운로드 URL입니다. 작업이 성공한 후 배열에 URL이 하나 들어가며, 그 전까지는 비어 있습니다.
image_urls[i]는candidate_ids[i]의 후보를 보여줍니다.이 URL들은 표시용입니다. 빌드 엔드포인트는 URL이 아니라
candidate_ids의 항목을 받습니다. 이는 서명된 URL이므로Authorization헤더 없이 가져오세요. 이 URL들은expires_at까지 유효하며, 작업을 다시 조회해도 동일한 URL이 반환됩니다.
- Name
- candidate_ids
- Type
- array of strings
- Description
image_urls와 같은 순서로 나열된 후보들의 ID입니다. 후보를 빌드하려면 빌드 요청에서 그 ID를candidate_id로 보내세요. 이 ID들의 형식에 의존하지 마세요.
The Keycap build task object
빌드 태스크는 성공한 프로토타입 태스크와 그 후보 중 하나로부터 텍스처가 적용된 3D 키캡을 생성합니다. 3D 모델을 생성하고, 색을 입히고, 키캡 베이스에 안착시켜 절단한 다음, 키캡을 조립하여 내보냅니다.
속성
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=***"
}
}
- Name
- id
- Type
- string
- Description
태스크 ID입니다. 형식에 의존하지 마세요.
- Name
- type
- Type
- string
- Description
태스크 유형이며, 항상
creative-lab-keycap-build입니다.
- Name
- name
- Type
- string
- Description
태스크를 생성할 때 전송한
name이며, 보내지 않았다면""입니다.
- Name
- status
- Type
- string
- Description
태스크의 상태입니다.
사용 가능한 값:
PENDING: 대기열에서 대기 중IN_PROGRESS: 결과 생성 중SUCCEEDED: 최종 상태이며, 결과 포함FAILED: 최종 상태이며, 사유는task_error에 있음CANCELED: 최종 상태이며, 결과 없음
- Name
- progress
- Type
- integer
- Description
작업 완료 비율로,
0부터100까지입니다. 태스크가 시작되기 전까지는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
태스크 결과가 만료되는 시간으로, 유닉스 밀리초 단위입니다.
finished_at이후 3일이며, 태스크가 완료되기 전까지는created_at이후 3일입니다. API 결과를 무기한 보관하는 Enterprise 계정의 경우, 약 100년 후입니다. 에셋 보존을 참고하세요.
- Name
- preceding_tasks
- Type
- integer
- Description
PENDING상태일 때 대기열에서의 태스크 위치입니다.1은 다음 차례로 시작됨을 의미합니다. 태스크가 대기열을 벗어나면0이 되며, 목록 결과에서는 항상0입니다.
- Name
- task_error
- Type
- object
- Description
태스크가 실패한 이유입니다.
status가FAILED가 아닌 한null입니다. 오류를 참고하세요.
- Name
- consumed_credits
- Type
- integer
- Description
환불 후 해당 태스크에 청구된 크레딧 수입니다. 오류를 반환하는 요청은 청구되지 않습니다. 실패한 태스크는 Meshy가 환불하므로
0입니다. 취소는 태스크가PENDING상태일 때만 환불됩니다. Meshy가 청구 내역을 읽을 수 없는 경우, get 또는 stream 응답에서는 이 필드가 생략되며, 목록 요청은500을 반환합니다. 이 경우 요청을 재시도하세요.
- Name
- model_urls
- Type
- object
- Description
3D 모델의 다운로드 URL입니다. Meshy는 GLB 파일과 OBJ 번들을 밀리미터 단위의 실제 축척으로, Y축이 위를 향하고 키캡의 앞면이 +Z를 향하도록 내보냅니다.
모델에는
keycap-head와keycap-base라는 이름의 메시가 있습니다. Meshy가 베이스에 패턴 채우기로 대체 처리한 경우, 모델에는 스템 캐비티용keycap-base-interior메시도 포함됩니다. 모델에 정확히 두 개의 메시만 있다고 가정하지 마세요.이 URL들은 서명된 URL이므로
Authorization헤더 없이 가져오세요.expires_at까지 유효하며, 그 전에 태스크를 다시 조회하면 동일한 URL이 반환됩니다. 만료된 URL은 갱신할 수 없으므로, 만료 전에 파일을 다운로드하여 저장하세요.- Name
glb- Type
- string
- Description
텍스처가 적용된 GLB 파일
model.glb의 다운로드 URL입니다.
- Name
obj_zip- Type
- string
- Description
OBJ 번들의 다운로드 URL로,
model.obj,model.mtl, 그리고model.mtl이 사용하는 PNG 텍스처가 포함된 ZIP 파일입니다. 단색 베이스인 경우 유일한 텍스처는keycap-head.png입니다. 패턴이 있는 베이스인 경우 ZIP 파일에keycap-base.png도 포함됩니다.
- Name
- process_image_urls
- Type
- object
- Description
빌드 단계에서 생성된 이미지의 다운로드 URL로, 종류별로 키가 지정되어 있습니다.
model_urls와 마찬가지로 서명된 URL이므로Authorization헤더 없이 가져오세요.expires_at까지 유효하며, 태스크를 다시 조회하면 동일한 URL이 반환됩니다.다음 키들을 가질 수 있습니다:
head_design: 빌드가 3D로 변환한, 선택된 후보의 디자인 이미지입니다. 항상 존재합니다.composite: 베이스에 색을 입히는 데 사용된, 선택된 후보에 대한 완성된 키캡의 이미지입니다. 없을 수 있습니다.base_canvas: 색이 입혀진 키캡 베이스입니다. 없을 수 있습니다.
Meshy가 키를 추가할 수 있으므로, 인식하지 못하는 키는 무시하세요.
End-to-end example
이 예제는 전체 플로우를 실행합니다:
- 사진으로 프로토타입 작업을 생성합니다.
- 작업의
status가SUCCEEDED가 될 때까지 작업을 조회합니다. candidate_ids에서 후보를 선택합니다.- 해당 후보로 빌드 작업을 생성합니다.
- 빌드 작업의
status가SUCCEEDED가 될 때까지 작업을 조회합니다. model_urls에서 GLB 파일과 OBJ 번들을 다운로드합니다.
이 예제는 첫 번째 후보를 선택합니다. 사용자 앱에서는 image_urls 항목을 사용자에게 보여주고 직접 선택하도록 하세요. 선택된 이미지의 image_urls 내 인덱스는 candidate_ids에 있는 해당 ID의 인덱스와 같습니다.
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://...
: "${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"