Keycap API для Creative Lab
Превратите фотографию в полноцветный кастомный колпачок для клавиш механической клавиатуры в два этапа. Задача прототипа генерирует изображение готового колпачка на основе фотографии. Задача сборки превращает это изображение в текстурированную 3D-модель колпачка. Она принимает ID задачи прототипа в качестве input_task_id и ID кандидата изображения в качестве candidate_id.
POST /openapi/creative-lab/keycap/v1/prototypePOST /openapi/creative-lab/keycap/v1/build
Оба endpoint'а POST требуют платный тариф. Запрос с бесплатного аккаунта возвращает 402.
Создать задачу прототипа Keycap
Генерирует одно изображение готового keycap по фото. Поле image_urls задачи содержит изображение, а candidate_ids — его ID, по одной записи в каждом. Если дизайн вам не понравился, создайте ещё одну задачу прототипа. Meshy взимает плату за каждую задачу прототипа отдельно.
Чтобы построить 3D-keycap, передайте 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
Фото, которое нужно превратить в дизайн keycap, в виде публичного URL или data URI (
data:image/jpeg;base64,<ваши данные изображения в base64>).Изображение должно быть файлом JPG, JPEG, PNG или WebP размером не более 20 МБ (20 000 000 байт). Каждая сторона должна быть не менее 32 пикселей, а изображение может содержать не более 178 956 970 пикселей в целом. Изображение за пределами этих ограничений возвращает
400.Meshy определяет формат по данным изображения, а не по расширению файла в URL. URL без расширения работает, и Meshy следует HTTP-редиректам. Meshy применяет ориентацию EXIF, поэтому повёрнутое фото с телефона отображается так, как оно выглядит на самом деле.
Data URI должен быть закодирован в base64 с указанием типа изображения, например
data:image/png;base64,..., а декодированное изображение должно быть JPEG, PNG или WebP. Ограничение в 20 МБ применяется к декодированному изображению, поэтому текст base64 может быть примерно на треть больше.
- Name
- name
- Type
- string
- Description
Название задачи, до 100 символов. Оно возвращается в поле
nameзадачи. Более длинное название возвращает400.
- Name
- remove_background
- Type
- boolean
- по умолчанию false
- Description
Следует ли удалять фон с изображения прототипа.
trueвозвращает прозрачный PNG в формате RGBA, так что вы можете разместить keycap на любом фоне. Если Meshy не может удалить фон, он возвращает изображение с его фоном, и задача всё равно завершается успешно.Дизайн головки, который сборка превращает в 3D, сохраняет свой фон в любом случае. Сборка окрашивает основание keycap по изображению из
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.
- Изображение слишком маленькое, превышает 20 МБ или превышает максимальное количество пикселей.
- Meshy не может скачать изображение, например потому что URL возвращает
404или превышено время ожидания. - Data URI не является корректным base64.
- Изображение было помечено как NSFW.
Сообщение об ошибке указывает, какая именно проблема была обнаружена. Исправьте запрос и отправьте его снова.
- Отсутствует
- Name
401 - Unauthorized- Description
API-ключ отсутствует или недействителен. Проверьте заголовок
Authorization.
- Name
402 - Payment Required- Description
Применимо одно из следующего:
- На аккаунте недостаточно кредитов.
- API-ключ, рабочая область или участник достигли лимита кредитов.
- Аккаунт работает по бесплатному плану.
Проверьте свои кредиты и план, затем повторите попытку.
- Name
403 - Forbidden- Description
В вашей команде включена функция IP Filtering, и Meshy пометил изображение как содержащее стороннюю интеллектуальную собственность. Отправьте изображение, на использование которого у вас есть права.
- Name
429 - Too Many Requests- Description
Был достигнут один из следующих лимитов:
- Вы отправили больше запросов, чем допускает ваше ограничение частоты. Подождите несколько секунд и повторите попытку. См. Ограничения частоты.
- Слишком много ваших задач находятся в очереди или выполняются. Дождитесь завершения некоторых из них, затем повторите попытку.
- На безлимитном плане без оставшихся кредитов вы достигли количества задач, которые могут выполняться без кредитов. Дождитесь завершения задачи или добавьте кредиты.
- Name
500 - Internal Server Error- Description
В Meshy произошла ошибка сервера, например потому что не удалось выполнить модерацию контента или проверку интеллектуальной собственности, либо Meshy не смог сохранить изображение. Meshy не создаёт задачу и возвращает все списанные кредиты. Повторите запрос.
Создать задачу сборки Keycap
Генерирует текстурированную 3D-модель клавиши (keycap) на основе успешно выполненной задачи-прототипа и одного из её кандидатов. Описание полей см. в разделе Объект задачи сборки Keycap.
Одна задача сборки выполняет все шаги. Она генерирует 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.ID, который не является одной из ваших задач-прототипов Keycap из API, возвращает
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-1x1-r1, стандартная клавиша профиля Cherry MX 1u. Пользовательские размеры не поддерживаются, и любое другое значение возвращает400.
- Name
- head_size_mm
- Type
- number
- по умолчанию 23
- Description
Размер головки вдоль её самого длинного измерения, в миллиметрах, от
10до40. Meshy масштабирует головку так, чтобы её самое длинное измерение соответствовало этому значению. Значение вне диапазона возвращает400.Для значения выше примерно
32.9Meshy может уменьшить размер, чтобы головка помещалась в пределах защитного контура основания. В этом случае головка может оказаться меньше, чем вы запросили. Объект задачи не возвращает размер, применённый Meshy. Чтобы проверить его, измерьте ограничивающий параллелепипед сеткиkeycap-headв модели.
- Name
- vertical_offset_mm
- Type
- number
- по умолчанию 0
- Description
Вертикальное смещение, применяемое к головке перед тем, как Meshy устанавливает её на основание, в миллиметрах, от
-5до5. Значение вне диапазона возвращает400.
Возвращаемое значение
Поле result содержит ID новой задачи сборки. Получите задачу или передавайте её потоком, пока status не станет SUCCEEDED. Затем загрузите файл GLB из model_urls.glb и пакет OBJ из model_urls.obj_zip.
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не соответствует ни одной задаче-прототипу Keycap, созданной вашей учётной записью через API. Прототип, созданный в веб-приложении, также возвращает404. Отправьте IDresultиз ответа на создание прототипа.
- Name
429 - Too Many Requests- Description
Был достигнут один из следующих лимитов:
- Вы отправили больше запросов, чем допускает ваше ограничение частоты. Подождите несколько секунд, затем повторите попытку. См. Ограничения частоты.
- Слишком много ваших задач находится в очереди или выполняется. Подождите, пока некоторые из них завершатся, затем повторите попытку.
- На безлимитном плане без оставшихся кредитов вы достигли количества задач, которые могут выполняться без кредитов. Подождите завершения задачи или добавьте кредиты.
- Name
500 - Internal Server Error- Description
Meshy не смогла создать задачу из-за ошибки сервера. Meshy возвращает любые списанные кредиты. Повторите запрос.
Получить задачу Keycap
Возвращает задачу прототипа или сборки. Путь должен соответствовать этапу задачи. Задача сборки, запрошенная через /prototype/:id, вернёт 404, и то же самое произойдёт с задачей прототипа, запрошенной через /build/:id.
Описание полей см. в разделах Объект задачи прототипа 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=***"
}
}
Параметры
- Name
- id
- Type
- path
- Description
ID задачи из ответа на создание.
Возвращает
Объект задачи прототипа или объект задачи сборки, в зависимости от этапа, указанного в пути.
Возможные ошибки
- Name
400 - Bad Request- Description
idне является допустимым ID задачи. Укажите IDresultиз ответа на создание.
- Name
403 - Forbidden- Description
В вашей команде включена функция IP Filtering, и Meshy пометил изображение задачи прототипа как нарушающее права интеллектуальной собственности третьих лиц. Задачи сборки и команды на тарифе Enterprise не получают эту ошибку. Создавайте задачу прототипа из изображения, на использование которого у вас есть права.
- Name
404 - Not Found- Description
Задача Keycap с этим ID не принадлежит вашему аккаунту, либо этап задачи не соответствует указанному пути. Проверьте ID и используйте
/prototypeили/buildв соответствии с задачей.
- Name
500 - Internal Server Error- Description
Meshy не удалось выполнить проверку интеллектуальной собственности. Повторите запрос.
Удаление задачи Keycap
Отменяет задачу Keycap. Отмена задачи со статусом PENDING возвращает затраченные кредиты. Задача со статусом IN_PROGRESS отменяется без возврата кредитов, поскольку воркер уже приступил к её выполнению. Задачу с финальным статусом (SUCCEEDED, FAILED или CANCELED) отменить нельзя.
Путь должен соответствовать этапу задачи. Например, запрос DELETE к /prototype/:id с ID задачи этапа build вернёт 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 задачи. Отправьте IDresultиз ответа на запрос создания.- Задача уже имеет финальный статус (
SUCCEEDED,FAILEDилиCANCELED), поэтому её нельзя отменить.
- Name
404 - Not Found- Description
Задача Keycap с таким ID не принадлежит вашему аккаунту, либо этап задачи не соответствует указанному пути. Проверьте ID и используйте
/prototypeили/buildв соответствии с задачей.
- Name
500 - Internal Server Error- Description
На стороне Meshy произошла ошибка сервера при отмене задачи, поэтому задача может быть как отменена, так и не отменена. Получите задачу, чтобы проверить её
status, прежде чем повторить попытку.
Получение обновлений задачи Keycap через поток
Передаёт обновления задачи Keycap в виде Server-Sent Events (SSE). Путь должен соответствовать этапу задачи. Если это не так, например ID задачи build используется по адресу /prototype/:id/stream, поток отправляет одно событие error со status_code: 404 и закрывается.
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 блокирует результат задачи, поток отправляет вместо него одно событие error с тем status_code, который вернул бы GET-запрос.
Список задач Keycap
Возвращает ваши задачи Keycap одного этапа, по одной странице за раз. Путь определяет этап. /prototype возвращает только задачи прототипа, а /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: сначала старые
Возвращает
Массив объектов задачи прототипа или объектов задачи сборки, соответствующих этапу, указанному в пути.
Объект задачи прототипа Keycap
Задача прототипа генерирует одно изображение готового колпачка клавиши (keycap) из фотографии. Чтобы превратить дизайн в 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_errorCANCELED: завершено, без результата
- Name
- progress
- Type
- integer
- Description
Процент выполненной работы, от
0до100. Равен0, пока задача не началась, и100, когда она завершена успешно.
- Name
- created_at
- Type
- timestamp
- Description
Время создания задачи, в миллисекундах Unix.
- Name
- started_at
- Type
- timestamp
- Description
Время, когда воркер начал выполнение задачи, в миллисекундах Unix.
nullдо этого момента.
- Name
- finished_at
- Type
- timestamp
- Description
Время, когда задача достигла финального статуса, в миллисекундах Unix.
nullдо этого момента.
- Name
- expires_at
- Type
- timestamp
- Description
Время истечения срока действия результата задачи, в миллисекундах Unix. Это 3 дня после
finished_at, или 3 дня послеcreated_at, пока задача не завершится. Для корпоративных (Enterprise) аккаунтов, которые хранят результаты API бессрочно, это примерно на 100 лет позже. См. Хранение ресурсов.
- Name
- preceding_tasks
- Type
- integer
- Description
Позиция задачи в очереди, пока она в статусе
PENDING.1означает, что она начнётся следующей.0после того, как задача покидает очередь, и всегда0в результатах списка.
- Name
- task_error
- Type
- object
- Description
Причина, по которой задача завершилась неудачей.
null, еслиstatusнеFAILED. См. Ошибки.
- Name
- consumed_credits
- Type
- integer
- Description
Количество кредитов, списанных за задачу, с учётом возврата. Запрос, возвращающий ошибку, не оплачивается. Для неудачной задачи значение
0, так как Meshy возвращает средства. Отмена возвращает средства за задачу только пока она в статусеPENDING. Если Meshy не может прочитать списание, ответ при получении задачи или потоковой передаче не содержит это поле, а запрос списка возвращает500. В этом случае повторите запрос.
- Name
- image_urls
- Type
- array of strings
- Description
URL-адреса для скачивания изображения готового колпачка клавиши. Массив содержит один URL после успешного завершения задачи и пуст до этого момента.
image_urls[i]показывает кандидата изcandidate_ids[i].Эти URL предназначены для отображения. Эндпоинт сборки принимает запись из
candidate_ids, а не URL. Это подписанные URL, поэтому запрашивайте их без заголовкаAuthorization. Они остаются действительными доexpires_at, и повторное получение задачи возвращает те же URL.
- Name
- candidate_ids
- Type
- array of strings
- Description
ID кандидатов, в том же порядке, что и
image_urls. Чтобы собрать кандидата, отправьте его ID какcandidate_idв запросе сборки. Не полагайтесь на формат этих ID.
Объект задачи сборки Keycap
Задача сборки генерирует текстурированный 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_errorCANCELED: финальный статус, без результата
- Name
- progress
- Type
- integer
- Description
Процент выполненной работы, от
0до100. Равен0до начала задачи и100, когда она завершается успешно.
- Name
- created_at
- Type
- timestamp
- Description
Время создания задачи, в миллисекундах Unix.
- Name
- started_at
- Type
- timestamp
- Description
Время, когда воркер начал выполнение задачи, в миллисекундах Unix.
nullдо этого момента.
- Name
- finished_at
- Type
- timestamp
- Description
Время, когда задача достигла финального статуса, в миллисекундах Unix.
nullдо этого момента.
- Name
- expires_at
- Type
- timestamp
- Description
Время истечения срока действия результата задачи, в миллисекундах Unix. Это 3 дня после
finished_at, либо 3 дня послеcreated_at, пока задача не завершится. Для аккаунтов Enterprise, которые хранят результаты API бессрочно, это значение указывает примерно на 100 лет вперёд. См. Хранение ресурсов.
- Name
- preceding_tasks
- Type
- integer
- Description
Позиция задачи в очереди, пока она находится в статусе
PENDING.1означает, что она начнётся следующей.0после того, как задача покидает очередь, и всегда0в результатах списка.
- Name
- task_error
- Type
- object
- Description
Причина, по которой задача завершилась неудачно.
null, еслиstatusне равенFAILED. См. Ошибки.
- Name
- consumed_credits
- Type
- integer
- Description
Количество кредитов, списанных за задачу, с учётом возможного возврата. Запрос, вернувший ошибку, не оплачивается. Для задачи, завершившейся неудачно, значение равно
0, поскольку Meshy возвращает кредиты. Отмена возвращает кредиты за задачу только пока она находится в статусеPENDING. Если Meshy не может определить сумму списания, поле отсутствует в ответе на запрос получения или потоковую передачу, а запрос списка возвращает500. В этом случае повторите запрос.
- Name
- model_urls
- Type
- object
- Description
URL-адреса для скачивания 3D-модели. Meshy экспортирует файл GLB и пакет OBJ в реальном масштабе в миллиметрах, с осью Y вверх, при этом передняя часть колпачка направлена вдоль +Z.
Модель содержит сетки с именами
keycap-headиkeycap-base. Когда Meshy использует запасной вариант с узорным заполнением для основания, модель также содержит сеткуkeycap-base-interiorдля полости штока. Не предполагайте, что модель содержит ровно две сетки.Это подписанные URL-адреса, поэтому запрашивайте их без заголовка
Authorization. Они остаются действительными доexpires_at, и повторное получение задачи до этого момента возвращает те же URL-адреса. Истёкший URL-адрес нельзя обновить, поэтому скачайте и сохраните файлы до истечения срока.- Name
glb- Type
- string
- Description
URL-адрес для скачивания текстурированного файла GLB,
model.glb.
- Name
obj_zip- Type
- string
- Description
URL-адрес для скачивания пакета OBJ — ZIP-файла с
model.obj,model.mtlи PNG-текстурами, которые используетmodel.mtl. Для основания сплошного цвета единственной текстурой является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. - Скачать файл GLB и архив OBJ из
model_urls.
В примере выбирается первый кандидат. В вашем приложении показывайте пользователям записи image_urls и дайте им возможность выбора. Индекс выбранного изображения в image_urls совпадает с индексом его ID в 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"