Creative Lab — Keycap API
แปลงภาพถ่ายต้นฉบับให้เป็นแป้นพิมพ์คีย์แคปแบบสีเต็มรูปแบบสำหรับคีย์บอร์ดแบบกลไก
ใน 2 ขั้นตอน: prototype จะสร้างภาพเรนเดอร์การออกแบบ "คีย์แคปที่เสร็จสมบูรณ์"
จากภาพถ่ายที่คุณนำเข้ามา เมื่อคุณยืนยันภาพเรนเดอร์นั้นแล้ว build จะแปลงให้เป็น
โมเดลคีย์แคป 3 มิติที่มีเทกซ์เจอร์ในการรันเพียงครั้งเดียว — การสร้างโมเดลสีขาว การจัดวางและ
การตัดอัตโนมัติบนท่าทางเริ่มต้นที่ผ่านการปรับเทียบแล้ว การลงสีทั้งโมเดล และ
การประกอบขั้นสุดท้ายทั้งหมดเกิดขึ้นภายในงานสร้างโมเดลเดียว ทั้งสองขั้นตอนเชื่อมโยงกัน
ผ่าน input_task_id และ candidate_id
POST /openapi/creative-lab/keycap/v1/prototypePOST /openapi/creative-lab/keycap/v1/build
ทั้งสอง endpoint แบบ POST จำเป็นต้องมีแผนการสมัครสมาชิกแบบชำระเงิน คำขอ
จากบัญชีแผนฟรีจะถูกปฏิเสธด้วย 402 Payment Required
สร้าง Keycap Prototype Task
สร้างภาพ render ของดีไซน์ keycap ที่เสร็จสมบูรณ์จากภาพถ่ายต้นฉบับ ผลลัพธ์ของ task
จะมี array image_urls (ภาพ render สำหรับแสดงผลของ keycap ที่เสร็จสมบูรณ์)
และ array candidate_ids ที่คู่กัน โดยทั้งสอง array จะมีรายการเดียว
เรียก endpoint นี้อีกครั้งเพื่อขอ render อื่นหากผลลัพธ์ยังไม่ตรงกับที่ต้องการ — แต่ละการเรียกจะถูกเรียกเก็บเงินแยกกัน ส่ง candidate_id
พร้อมกับ prototype task ID ไปยัง build endpoint
ดูรูปแบบของ response ได้ที่
The Keycap Prototype Task Object
พารามิเตอร์
- Name
- image_url
- Type
- string
- จำเป็น
- Description
ภาพถ่ายต้นฉบับที่ให้ Meshy แปลงเป็นภาพดีไซน์ keycap ปัจจุบันเรารองรับรูปแบบ
.jpg,.jpeg,.png, และ.webpรูปแบบไฟล์จะถูกตรวจสอบจากการถอดรหัสข้อมูลภาพ ไม่ใช่ จากนามสกุลไฟล์ใน URL — URL ที่ไม่มีนามสกุล หรือ URL ที่มีการ redirect ก็ใช้งานได้ตราบใดที่ไบต์สามารถถอดรหัสเป็นรูปแบบที่รองรับ ระบบจะติดตาม HTTP redirect ให้ ทิศทางของภาพ (EXIF orientation) จะถูกปรับให้เป็นปกติ ดังนั้นภาพถ่ายจากโทรศัพท์ที่หมุนไว้จะถูกใช้งานตามที่แสดงผลจริง
ข้อจำกัด: ด้านแต่ละด้านอย่างน้อย
32พิกเซล รวมทั้งหมดไม่เกิน178,956,970พิกเซล และไม่เกิน20,000,000ไบต์เมื่อดาวน์โหลดแล้ว สำหรับ Data URI ข้อจำกัดจะใช้กับไบต์ที่ถอดรหัสแล้ว ดังนั้นไฟล์ต้นฉบับเองอาจมีขนาดได้ถึงขนาดนั้น — เป็นข้อความ base64 ที่มีขนาดใหญ่กว่าประมาณหนึ่งในสาม ซึ่งมีผลต่อ request body ของคุณ ไม่ใช่ต่อข้อจำกัดนี้ Data URI ต้องระบุ content type เป็นimage/*และ;base64มีสองวิธีในการระบุภาพ:
- URL ที่เข้าถึงได้แบบสาธารณะ: URL ที่สามารถเข้าถึงได้จากอินเทอร์เน็ตสาธารณะ
- Data URI: Data URI ของภาพที่เข้ารหัสแบบ base64 ตัวอย่างของ Data URI:
data:image/jpeg;base64,<your base64-encoded image data>
- Name
- name
- Type
- string
- Description
ชื่อ task ที่ไม่บังคับสำหรับการแสดงผล สูงสุด 100 ตัวอักษร
- Name
- remove_background
- Type
- boolean
- ค่าเริ่มต้น false
- Description
เมื่อตั้งค่าเป็น
trueภาพ render สำหรับแสดงผลที่ส่งกลับในimage_urlsจะเป็น PNG แบบ RGBA โปร่งใสที่ลบพื้นหลังออกแล้ว ทำให้คุณสามารถนำไปประกอบกับพื้นหลังใดก็ได้ผลนี้จะมีผลกับภาพ render สำหรับแสดงผลเท่านั้น candidate ที่ build endpoint ใช้จะไม่ได้รับผลกระทบ ดังนั้นผลลัพธ์ 3D จะเหมือนกันไม่ว่าจะเลือกค่าใด
ผลลัพธ์ที่ได้รับ
พร็อพเพอร์ตี้ result ของ response จะมี id ของ keycap prototype task ที่สร้างขึ้นใหม่ ให้ทำการ poll ที่ endpoint Get a Task หรือ subscribe ที่ stream จนกว่า task จะมีสถานะ SUCCEEDED จากนั้นนำรายการจาก candidate_ids พร้อมกับ task ID ไปส่งยัง build endpoint
รูปแบบความล้มเหลว
- Name
400 - Bad Request- Description
คำขอไม่สามารถยอมรับได้ สาเหตุที่พบบ่อย:
- ขาดพารามิเตอร์: ต้องระบุ
image_url - รูปแบบภาพไม่ถูกต้อง:
image_urlที่ระบุไม่ใช่รูปแบบที่รองรับ (.jpg,.jpeg,.png,.webp) - ขนาดภาพอยู่นอกช่วงที่กำหนด: ภาพมีขนาดเล็กเกินไป เกินขนาดไฟล์สูงสุด หรือเกินจำนวนพิกเซลสูงสุด
- URL ไม่สามารถเข้าถึงได้: ไม่สามารถดาวน์โหลด
image_urlได้ (404 หรือ timeout) - Data URI ไม่ถูกต้อง: สตริง base64 มีรูปแบบผิดพลาด
- เนื้อหาถูกตั้งค่าสถานะ: ภาพที่ป้อนเข้ามาถูกตั้งค่าสถานะโดยระบบ moderation เนื้อหา NSFW
- ขาดพารามิเตอร์: ต้องระบุ
- Name
401 - Unauthorized- Description
การยืนยันตัวตนล้มเหลว โปรดตรวจสอบ API คีย์ของคุณ
- Name
402 - Payment Required- Description
บัญชีนี้อยู่ในแพ็กเกจฟรี (ต้องใช้แพ็กเกจแบบชำระเงินเพื่อสร้าง task) หรือมีเครดิตไม่เพียงพอ
- Name
403 - Forbidden- Description
ภาพที่ป้อนเข้ามาถูกตั้งค่าสถานะโดยระบบ moderation ด้านทรัพย์สินทางปัญญา
- Name
429 - Too Many Requests- Description
คุณส่งคำขอเกินการจำกัดอัตราที่กำหนดไว้
- Name
500 - Internal Server Error- Description
เกิดข้อผิดพลาดที่ไม่คาดคิดฝั่งเซิร์ฟเวอร์ — ตัวอย่างเช่น บริการ moderation เนื้อหาไม่พร้อมใช้งาน การเตรียมภาพที่ป้อนเข้ามาล้มเหลว หรือไม่สามารถสร้าง task ได้ ในกรณีนี้จะไม่มีการสร้าง task ขึ้น ดังนั้นการลองใหม่จึงปลอดภัย
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"
}
Create a Keycap Build Task
สร้างโมเดล keycap 3D ที่มีพื้นผิวสมบูรณ์จาก prototype task ที่สำเร็จแล้วและหนึ่งใน candidate ของมัน build task เดียวจะรันทั้งไปป์ไลน์แบบ end to end — การสร้าง white-model จากดีไซน์ที่เลือก, การจัดวางและตัดอัตโนมัติลงบน keycap base โดยใช้ท่าทางค่าเริ่มต้นที่ได้รับการปรับเทียบไว้ (ไม่ต้องปรับแต่งแบบโต้ตอบ), การลงสีทั้งโมเดล และการประกอบและส่งออกขั้นสุดท้าย โดยทั่วไป build จะใช้เวลา 3–7 นาที โดยจะเข้าใกล้ช่วงเวลาสูงสุดเมื่อมี build หลายรายการทำงานพร้อมกัน ดูรูปแบบของการตอบกลับได้ที่ The Keycap Build Task Object
พารามิเตอร์
- Name
- input_task_id
- Type
- string
- จำเป็น
- Description
รหัสของ task ของ prototype ที่สร้างขึ้นผ่านเอนด์พอยต์ OpenAPI เดียวกันนี้ prototype นี้ต้องถูกสร้างโดยบัญชี Meshy เดียวกัน ต้องมีสถานะถึง
SUCCEEDEDแล้ว และต้องสร้าง candidate อย่างน้อยหนึ่งรายการprototype task ที่สร้างผ่าน webapp จะไม่ ได้รับการยอมรับ — เอนด์พอยต์ build จะยอมรับเฉพาะ prototype task ที่สร้างจาก
POST /openapi/creative-lab/keycap/v1/prototypeเท่านั้น และจะปฏิเสธแหล่งที่มาอื่นใดด้วย404
- Name
- candidate_id
- Type
- string
- จำเป็น
- Description
candidate ที่จะนำมา build โดยนำมาจากอาร์เรย์
candidate_idsของ prototype task ที่สำเร็จแล้ว ต้องเป็นของ task นั้นเท่านั้น ค่าอื่นใดจะถูกปฏิเสธด้วย400
- Name
- name
- Type
- string
- Description
ชื่อ task ที่ไม่บังคับสำหรับใช้แสดงผล สูงสุด 100 ตัวอักษร
options
การปรับแต่งจีออเมทรีที่ไม่บังคับ ทุกฟิลด์มีค่าเริ่มต้นที่ได้รับการปรับเทียบไว้แล้ว — ให้ส่งเฉพาะฟิลด์ที่ต้องการเปลี่ยนแปลงเท่านั้น
- Name
- base_model
- Type
- string
- ค่าเริ่มต้น cherry-mx-1x1-r1
- Description
keycap base ที่จะนำมา build ปัจจุบันมีค่าเดียวที่ใช้ได้คือ
cherry-mx-1x1-r1— keycap 1u โปรไฟล์ Cherry MX มาตรฐาน มีแผนจะเพิ่มขนาดมาตรฐานที่ใช้ทั่วไปอีก 3–5 ขนาด ส่วนขนาดที่กำหนดเองยังไม่รองรับ
- Name
- head_size_mm
- Type
- number
- ค่าเริ่มต้น 23
- Description
ขนาดเป้าหมายของหัวที่ปั้นขึ้น หน่วยเป็นมิลลิเมตร: มิติที่ยาวที่สุดจะถูกปรับสเกลให้ตรงกับค่านี้ ช่วงค่า:
[10, 40]ค่าที่สูงกว่าประมาณ32.9อาจถูกลดลงเพื่อให้หัวยังคงพอดีกับขีดจำกัดพื้นที่ป้องกันของฐาน ดังนั้นมิติที่ยาวที่สุดที่ได้จริงอาจเล็กกว่าค่าที่ร้องขอ ค่าที่นำไปใช้จริงในปัจจุบันยังไม่ถูกส่งกลับมาใน task object — หากต้องการยืนยันขนาดที่ได้รับจริง ให้วัดกล่องขอบเขตของเมชkeycap-headในโมเดลที่ดาวน์โหลดมา
- Name
- vertical_offset_mm
- Type
- number
- ค่าเริ่มต้น 0
- Description
ค่าออฟเซ็ตแนวตั้งที่นำไปใช้กับหัวก่อนจะนำไปวางบนฐาน หน่วยเป็นมิลลิเมตร ช่วงค่า:
[-5, 5]
ค่าที่ส่งกลับ
พร็อพเพอร์ตี้ result ของการตอบกลับจะมี id ของ task การ build keycap ที่สร้างขึ้นใหม่ ให้ทำการ poll เอนด์พอยต์ Get a Task หรือ subscribe ไปที่ stream จนกว่า task จะมีสถานะเป็น SUCCEEDED จากนั้นจึงดาวน์โหลด artifact จาก model_urls.glb และ model_urls.obj_zip
ทั้ง GLB และชุด OBJ จะถูกส่งออกโดยใช้ สเกลมิลลิเมตรตามขนาดจริง ด้วยระบบพิกัดแบบ Y-up และด้านหน้าของ keycap หันไปทาง +Z
รูปแบบความล้มเหลว
- Name
400 - Bad Request- Description
คำขอไม่สามารถยอมรับได้ สาเหตุทั่วไป:
- ขาดพารามิเตอร์: ต้องมี
input_task_idและcandidate_id - UUID ไม่ถูกต้อง:
input_task_idไม่ใช่ UUID ที่ถูกต้อง - task ต้นทางยังไม่สำเร็จ: prototype task ที่อ้างอิงยังไม่มีสถานะถึง
SUCCEEDED - ไม่มี candidate: prototype task สำเร็จแล้วแต่ไม่ได้สร้าง candidate ใดๆ
- candidate ไม่รู้จัก:
candidate_idไม่ใช่หนึ่งใน candidate ของ input task นั้น - options เกินขอบเขต: หนึ่งในฟิลด์ของ
optionsมีค่าอยู่นอกช่วงหรือชุดค่า enum ที่อนุญาต
- ขาดพารามิเตอร์: ต้องมี
- Name
401 - Unauthorized- Description
การยืนยันตัวตนล้มเหลว โปรดตรวจสอบ API คีย์ของคุณ
- Name
402 - Payment Required- Description
บัญชีนี้อยู่ในแพ็กเกจฟรี (จำเป็นต้องมีแพ็กเกจแบบชำระเงินเพื่อสร้าง task) หรือมีเครดิตไม่เพียงพอ
- Name
404 - Not Found- Description
prototype task ที่อ้างอิงไม่มีอยู่ เป็นของผู้ใช้รายอื่น หรือถูกสร้างผ่าน webapp (มีเพียง prototype task ในโหมด API เท่านั้นที่สามารถต่อยอดไปเป็น build ได้)
- Name
429 - Too Many Requests- Description
คุณได้เกินการจำกัดอัตราของคุณแล้ว
- Name
500 - Internal Server Error- Description
เกิดข้อผิดพลาดที่ไม่คาดคิดฝั่งเซิร์ฟเวอร์ — ตัวอย่างเช่น บริการ content-moderation ไม่พร้อมใช้งาน การเตรียมภาพอินพุตล้มเหลว หรือไม่สามารถสร้าง task ได้ ในกรณีนี้จะไม่มีการสร้าง task ใดๆ ดังนั้นสามารถลองใหม่ได้อย่างปลอดภัย
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"
}
Retrieve a Keycap Task
ดึงข้อมูลงาน prototype หรือ build โดยระบุ task id ที่ถูกต้อง URL path
ต้องตรงกับขั้นตอนของงาน — หากงาน build ถูกเรียกผ่าน
/prototype/:id จะได้รับ 404 และในทางกลับกันก็เช่นกัน
ดูรูปแบบการตอบกลับได้ที่ The Keycap Prototype Task Object และ The Keycap Build Task Object
พารามิเตอร์
- Name
- id
- Type
- path
- Description
ตัวระบุที่ไม่ซ้ำกันสำหรับงาน keycap ที่ต้องการดึงข้อมูล
ค่าที่ส่งกลับ
การตอบกลับจะประกอบด้วยอ็อบเจ็กต์งาน keycap รูปแบบขึ้นอยู่กับ ขั้นตอนที่ร้องขอ
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=***"
}
}
ลบงาน Keycap
ยกเลิกงาน keycap หากงานยังอยู่ในสถานะ PENDING เครดิตที่ถูกใช้ไป
ในขณะสร้างงานจะถูกคืนกลับ งานที่อยู่ในสถานะ
IN_PROGRESS แล้วจะถูกยกเลิกโดยไม่มีการคืนเครดิต (เนื่องจาก worker อาจกำลังใช้
แหล่งข้อมูลอยู่แล้ว) งานที่ไปถึงสถานะสุดท้ายแล้ว
(SUCCEEDED, FAILED, CANCELED) จะไม่สามารถยกเลิกได้
เส้นทาง URL ต้องตรงกับขั้นตอน (stage) ของงานนั้น ๆ — การเรียก DELETE ที่
/prototype/:buildId จะคืนค่า 404
พารามิเตอร์เส้นทาง (Path Parameters)
- Name
- id
- Type
- path
- Description
รหัสเฉพาะของงาน keycap ที่ต้องการยกเลิก
ผลลัพธ์ที่ได้รับ
คืนค่า 204 No Content เมื่อสำเร็จ พร้อม body ที่ว่างเปล่า
รูปแบบความล้มเหลว
- Name
400 - Bad Request- Description
งานนี้อยู่ในสถานะสุดท้ายแล้วและไม่สามารถยกเลิกได้
- Name
404 - Not Found- Description
ไม่พบงานนี้ งานนี้เป็นของผู้ใช้อื่น หรือขั้นตอนของงานไม่ตรงกับเส้นทาง URL
- Name
500 - Internal Server Error- Description
เกิดข้อผิดพลาดที่ไม่คาดคิดฝั่งเซิร์ฟเวอร์ระหว่างการยกเลิก งานอาจถูกยกเลิกแล้วหรือยังไม่ถูกยกเลิก — โปรดอ่านข้อมูลงานอีกครั้งเพื่อยืนยันก่อนลองใหม่
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).
สตรีมข้อมูลงาน Keycap Task
สตรีมข้อมูลอัปเดตแบบเรียลไทม์สำหรับงาน keycap ผ่าน Server-Sent Events (SSE)
เส้นทาง URL ต้องตรงกับขั้นตอนของงาน — การเปิดสตรีมที่
/prototype/:buildId/stream จะส่งเพย์โหลด event: error เพียงรายการเดียวที่มี
status_code: 404 แล้วปิดสตรีม
พารามิเตอร์
- Name
- id
- Type
- path
- Description
ตัวระบุเฉพาะสำหรับงาน keycap ที่ต้องการสตรีม
ค่าที่ส่งกลับ
ส่งกลับสตรีมของอ็อบเจ็กต์งาน Keycap Prototype
หรือ Keycap Build ในรูปแบบ
Server-Sent Events แต่ละเฟรมจะมีอ็อบเจ็กต์งานฉบับสมบูรณ์ของขั้นตอนนั้น ๆ — ในรูปแบบเดียวกับที่
เอนด์พอยต์ Get ส่งกลับ — ดังนั้นในขณะที่งานยังอยู่ในสถานะ PENDING หรือ IN_PROGRESS
ฟิลด์ผลลัพธ์ต่าง ๆ จะยังไม่ถูกกำหนดค่า (null, [] หรือ {}) และ
finished_at จะเป็น null
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 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=***"
}
}
List Keycap Tasks
ดึงรายการงาน keycap ของคุณแบบแบ่งหน้าสำหรับสเตจเดียว พาธ URL
จะเป็นตัวเลือกสเตจ — /prototype จะส่งคืนงานต้นแบบ (prototype); /build
จะส่งคืนงานสร้าง (build) งานจากอีกสเตจหนึ่งจะไม่ถูกรวมอยู่ในการตอบกลับ
ใด ๆ ทั้งสองแบบ
Path Parameters
- Name
- stage
- Type
- path
- จำเป็น
- Description
เป็นได้ทั้ง
prototypeหรือbuildคอลเลกชันจะส่งคืนเฉพาะงาน ที่มีสเตจตรงกับ URL — การเรียก/prototypeจะไม่ส่งคืนงาน build เลย และในทางกลับกันก็เช่นกัน
Query Parameters
- 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: เรียงตามเวลาที่สร้างจากมากไปน้อย
Returns
ส่งคืนรายการแบบแบ่งหน้าของอ็อบเจ็กต์งานเฉพาะสเตจ — อาจเป็น
อ็อบเจ็กต์งานต้นแบบ keycap
เมื่อดึงรายการจาก /prototype หรือ
อ็อบเจ็กต์งานสร้าง keycap เมื่อ
ดึงรายการจาก /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"
]
}
]
The Keycap Prototype Task Object
Keycap Prototype Task object คือหน่วยงานที่ Meshy คอยติดตามเพื่อสร้าง รูปภาพดีไซน์คีย์แคปฉบับสมบูรณ์ หนึ่งภาพจากภาพถ่ายต้นฉบับ ผลลัพธ์ของขั้นตอนนี้จะถูกส่งต่อไปยัง ขั้นตอนการ build ผ่านทาง input_task_id ร่วมกับ candidate_id
พร็อพเพอร์ตี้
- Name
- id
- Type
- string
- Description
ตัวระบุที่ไม่ซ้ำกันสำหรับ task แม้ว่าในทางปฏิบัติเราจะใช้ k-sortable UUID เป็น task id แต่คุณไม่ควรตั้งสมมติฐานใดๆ เกี่ยวกับรูปแบบของ id นี้
- Name
- type
- Type
- string
- Description
ประเภทของ task ค่านี้คือ
creative-lab-keycap-prototype
- Name
- name
- Type
- string
- Description
ชื่อ task ที่ระบุไว้ตอนสร้าง task เป็นสตริงว่างหากไม่ได้ระบุชื่อไว้
- Name
- status
- Type
- string
- Description
สถานะของ task ค่าที่เป็นไปได้คือ
PENDING,IN_PROGRESS,SUCCEEDED,FAILED,CANCELED
- Name
- progress
- Type
- integer
- Description
progress ของ task หาก task ยังไม่ได้เริ่ม พร็อพเพอร์ตี้นี้จะเป็น
0เมื่อ task สำเร็จแล้ว ค่านี้จะกลายเป็น100
- Name
- created_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่สร้าง task หน่วยเป็นมิลลิวินาที
ไทม์สแตมป์คือจำนวนมิลลิวินาทีที่ผ่านไปนับตั้งแต่วันที่ 1 มกราคม 1970 UTC ตามมาตรฐาน RFC 3339
ตัวอย่างเช่น วันศุกร์ที่ 1 กันยายน 2023 เวลา 12:00:00 น. GMT จะแสดงเป็น1693569600000ซึ่งใช้กับ ไทม์สแตมป์ทั้งหมดใน Meshy API
- Name
- started_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่ task เริ่มทำงาน หน่วยเป็นมิลลิวินาที หาก task ยังไม่ได้เริ่ม พร็อพเพอร์ตี้นี้จะเป็น
0
- Name
- finished_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่ task เสร็จสิ้น หน่วยเป็นมิลลิวินาที หาก task ยังไม่เสร็จสิ้น พร็อพเพอร์ตี้นี้จะเป็น
0
- Name
- expires_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่ผลลัพธ์ของ task จะหมดอายุ หน่วยเป็นมิลลิวินาที
- Name
- preceding_tasks
- Type
- integer
- Description
จำนวนของ task ที่อยู่ก่อนหน้า
ค่าของฟิลด์นี้จะมีความหมายก็ต่อเมื่อสถานะของ task เป็น
PENDINGเท่านั้น
- Name
- task_error
- Type
- object
- Description
รายละเอียดข้อผิดพลาดสำหรับ task ที่ล้มเหลว ดู ข้อผิดพลาด สำหรับข้อมูลอ้างอิงฉบับสมบูรณ์ของอ็อบเจ็กต์
task_error
- Name
- consumed_credits
- Type
- integer
- Description
จำนวนเครดิตที่ถูกใช้ไปโดย task นี้ task ที่มีสถานะถึง
SUCCEEDEDจะถูกเรียกเก็บเครดิตเต็มจำนวนสำหรับขั้นตอนนั้น ส่วน task ที่ไม่เคยถูกสร้างขึ้นเลย (เกิด4xxตอนที่ส่งคำขอ รวมถึงกรณีถูกปฏิเสธจาก moderation) จะไม่ถูกเรียกเก็บเครดิตเลย task ที่มีสถานะถึงFAILEDจะคืนค่าเป็น0— เครดิตที่ถูกเรียกเก็บจะถูกคืนกลับ รวมถึงกรณีถูกบล็อกโดย moderation แบบ asynchronous การยกเลิกผ่านDELETEจะคืนเครดิตให้ก็ต่อเมื่อ task ยังอยู่ในสถานะPENDINGเท่านั้น ส่วน task ที่เป็นIN_PROGRESSอยู่แล้วจะยังคงถูกเรียกเก็บเครดิต เนื่องจากงานได้ถูกใช้ไปแล้ว
- Name
- image_urls
- Type
- array of strings
- Description
URL สำหรับดาวน์โหลดภาพเรนเดอร์ดีไซน์คีย์แคปฉบับสมบูรณ์ — ลักษณะที่แคนดิเดตจะปรากฏเมื่อกลายเป็นคีย์แคปฉบับสมบูรณ์ มีเพียงหนึ่งรายการเท่านั้น โดย
image_urls[i]จะสอดคล้องกับcandidate_ids[i]ค่านี้จะว่างเปล่าจนกว่า task จะมีสถานะเป็นSUCCEEDEDURL นี้มีไว้สำหรับการแสดงผลเท่านั้น เอนด์พอยต์สำหรับ build จะใช้candidate_idsไม่ใช่ URL เหล่านี้ วงจรชีวิตของ URL เหมือนกับmodel_urlsคือ: มีการลงนาม ไม่ต้องใช้ headerAuthorizationใช้ได้จนถึงexpires_atและคงที่เมื่ออ่าน task ซ้ำ
- Name
- candidate_ids
- Type
- array of strings
- Description
ตัวระบุแคนดิเดตแบบทึบ (opaque) ที่สอดคล้องกับ
image_urlsให้ส่งรายการที่ตรงกับดีไซน์ที่คุณเลือกเป็นcandidate_idในคำขอ build ห้ามตั้งสมมติฐานใดๆ เกี่ยวกับรูปแบบของ 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"
]
}
The Keycap Build Task Object
Keycap Build Task object เป็นหน่วยงานที่ Meshy ใช้ติดตามการสร้างคีย์แคป 3D ที่มีเท็กซ์เจอร์สมบูรณ์จาก prototype task ที่สำเร็จแล้วและ candidate ที่เลือกไว้ การ build หนึ่งครั้งจะรัน pipeline ทั้งหมด ได้แก่ การสร้าง white-model, การจัดวางและตัดอัตโนมัติ, การลงสี, การประกอบ และการส่งออก
Properties
- Name
- id
- Type
- string
- Description
ตัวระบุที่ไม่ซ้ำกันสำหรับ task
- Name
- type
- Type
- string
- Description
ประเภทของ task ค่านี้คือ
creative-lab-keycap-build
- Name
- name
- Type
- string
- Description
ชื่อ task ที่ระบุไว้ตอนสร้าง task เป็นสตริงว่างหากไม่ได้ระบุชื่อไว้
- Name
- status
- Type
- string
- Description
สถานะของ task ค่าที่เป็นไปได้คือค่าใดค่าหนึ่งจาก
PENDING,IN_PROGRESS,SUCCEEDED,FAILED,CANCELED
- Name
- progress
- Type
- integer
- Description
progress ของ task หาก task ยังไม่เริ่มทำงาน property นี้จะเป็น
0เมื่อ task สำเร็จแล้ว ค่านี้จะกลายเป็น100
- Name
- created_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่สร้าง task หน่วยเป็นมิลลิวินาที
- Name
- started_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่เริ่ม task หน่วยเป็นมิลลิวินาที
- Name
- finished_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่ task เสร็จสิ้น หน่วยเป็นมิลลิวินาที
- Name
- expires_at
- Type
- timestamp
- Description
ไทม์สแตมป์ของเวลาที่ผลลัพธ์ของ task จะหมดอายุ หน่วยเป็นมิลลิวินาที
- Name
- preceding_tasks
- Type
- integer
- Description
จำนวน task ที่อยู่ก่อนหน้า มีความหมายเฉพาะเมื่อสถานะเป็น
PENDING
- Name
- task_error
- Type
- object
- Description
รายละเอียดข้อผิดพลาดสำหรับ task ที่ล้มเหลว ดู ข้อผิดพลาด สำหรับข้อมูลอ้างอิงฉบับเต็มของ object
task_error
- Name
- consumed_credits
- Type
- integer
- Description
จำนวนเครดิตที่ถูกใช้ไปโดย task นี้ task ที่มีสถานะถึง
SUCCEEDEDจะถูกเรียกเก็บเครดิตเต็มจำนวนสำหรับขั้นตอนของมัน ส่วน task ที่ไม่เคยถูกสร้างขึ้นเลย (เกิด4xxตอนที่ส่งคำขอ รวมถึงการถูกปฏิเสธจาก moderation) จะไม่ถูกเรียกเก็บเครดิตเลย task ที่มีสถานะถึงFAILEDจะคืนค่าเป็น0— เครดิตที่ถูกเรียกเก็บจะถูกคืนเงิน รวมถึงกรณีถูก moderation บล็อกแบบ asynchronous ด้วย การยกเลิกผ่านDELETEจะคืนเครดิตเฉพาะในขณะที่ task ยังเป็นPENDINGเท่านั้น ส่วน task ที่เป็นIN_PROGRESSอยู่แล้วจะยังคงถูกเรียกเก็บเครดิต เนื่องจากงานได้ถูกใช้ไปแล้ว
- Name
- model_urls
- Type
- object
- Description
URL สำหรับดาวน์โหลด artifact ของโมเดลที่สร้างขึ้น ทั้ง GLB และชุด OBJ จะถูกส่งออกในสเกล มิลลิเมตรตามขนาดจริง (real-world), แกน Y เป็นด้านบน (Y-up) โดยด้านหน้าของคีย์แคปหันไปทาง +Z เมชจะถูกตั้งชื่อว่า
keycap-headและkeycap-base; เมื่อฐาน (base) ตกไปใช้การเติมลวดลาย (pattern fill) แทน จะมีเมชที่สามคือkeycap-base-interiorปรากฏด้วยสำหรับช่องว่างของก้าน (stem cavity) อย่าตั้งสมมติฐานว่าจะมีเมชเพียงสองชิ้นเสมอไปURL เหล่านี้เป็น signed URL: ให้เรียกใช้งานโดยไม่ต้องใส่ header
AuthorizationURL จะยังใช้งานได้จนถึงexpires_atซึ่งคือ 3 วันหลังจากfinished_atและการอ่าน task ซ้ำภายในช่วงเวลานั้นจะได้ URL เดิมกลับมา ไม่ใช่ URL ที่ signed ใหม่ ควรดาวน์โหลดและจัดเก็บไฟล์ด้วยตัวเองก่อนที่จะหมดเวลาดังกล่าว เนื่องจากไม่มีวิธีใดที่จะรีเฟรชลิงก์ที่หมดอายุแล้วได้- Name
glb- Type
- string
- Description
URL สำหรับดาวน์โหลด
model.glbที่มีเท็กซ์เจอร์สมบูรณ์แล้ว
- Name
obj_zip- Type
- string
- Description
URL สำหรับดาวน์โหลดชุดไฟล์ zip ที่ประกอบด้วย
model.obj,model.mtlและไฟล์ PNG ของเท็กซ์เจอร์ที่ไฟล์ MTL ของมันอ้างอิงถึงจริง ๆ ฐาน (base) ที่เป็นสีทึบจะมีเฉพาะkeycap-head.pngส่วนฐานที่มีลวดลาย (patterned) จะมีkeycap-base.pngด้วย
- Name
- process_image_urls
- Type
- object
- Description
URL สำหรับดาวน์โหลดภาพขั้นตอนกลาง (intermediate process images) โดยจัดกลุ่มตามประเภท (kind) มี URL lifecycle เดียวกันกับ
model_urls: เป็น signed URL, ไม่ต้องใส่ headerAuthorization, ใช้งานได้จนถึงexpires_atและคงที่เมื่ออ่าน task ซ้ำ ประเภทที่ส่งออกในปัจจุบันได้แก่:head_design— ภาพดีไซน์ของ candidate ที่ถูกเลือกซึ่งใช้ในการ build (มีอยู่เสมอ)composite— ภาพเรนเดอร์แสดงคีย์แคปที่เสร็จสมบูรณ์ของ candidate ที่ถูกเลือก (มีเมื่อสามารถสร้างได้)base_canvas— canvas ของฐานคีย์แคปที่ลงสีแล้ว (มีเมื่อสามารถสร้างได้)
ควรถือว่าชุดคีย์นี้เปิดกว้างสำหรับการขยายเพิ่มเติม อาจมีการเพิ่มประเภทใหม่ ๆ โดยไม่ถือเป็นการเปลี่ยนแปลงที่ทำให้ใช้งานไม่ได้ (breaking change)
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=***"
}
}
ตัวอย่างการทำงานแบบครบวงจร
กระบวนการทั้งหมด: สร้างต้นแบบ (prototype) จากรูปภาพ, โพลจนกว่าจะได้สถานะ
SUCCEEDED, เลือกตัวเลือกจาก candidate_ids, สร้างงานสร้างโมเดล (build) ด้วย
ตัวเลือกนั้น, โพลงานสร้างโมเดลจนกว่าจะได้สถานะ SUCCEEDED จากนั้นดาวน์โหลด GLB และ
ชุด OBJ จาก model_urls
ตัวอย่างนี้จะเลือกตัวเลือก แรก โดยอัตโนมัติผ่านโปรแกรม ในการใช้งานจริง
คุณควรแสดงรายการ image_urls ให้ผู้ใช้ปลายทางเห็นและ
ให้พวกเขาเลือกเอง โดยดัชนีที่เลือกจะสอดคล้อง 1:1 กับ candidate_ids
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"