Преобразуйте исходное фото в полноцветную индивидуальную механическую клавишу клавиатуры в два этапа: прототип генерирует рендер "готовой клавиши" из вашего исходного фото. После того как вы подтвердите этот рендер, сборка превращает его в текстурированную 3D-модель клавиши за один запуск — генерация белой модели, автоматическая установка и обрезка в откалиброванной стандартной позе, полное окрашивание модели и окончательная сборка происходят в одной задаче сборки. Два этапа связаны через input_task_id плюс candidate_id.
POST /openapi/creative-lab/keycap/v1/prototype
POST /openapi/creative-lab/keycap/v1/build
Оба POST endpoint требуют платного плана подписки. Запросы от аккаунтов с бесплатным планом отклоняются с 402 Payment Required.
Создайте рендер дизайна готовой клавиши из исходного фото. Результат задачи содержит массив image_urls (рендер отображения готовой клавиши) и параллельный массив candidate_ids; оба содержат одну запись. Вызовите этот эндпоинт снова для другого рендера, если результат не соответствует вашим ожиданиям — каждый вызов оплачивается отдельно. Передайте candidate_id вместе с ID задачи прототипа в эндпоинт сборки. Обратитесь к
Объект задачи прототипа клавиши
для формы ответа.
Параметры
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 текст, который примерно на треть больше, что важно для тела вашего запроса, но не для этого ограничения. Data URI должен объявлять тип содержимого image/* и ;base64.
Есть два способа предоставить изображение:
Публично доступный 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 с удаленным фоном, чтобы вы могли наложить его на любой фон.
Это относится только к рендеру отображения. Кандидат, который потребляет эндпоинт сборки, не затрагивается, поэтому 3D-результат идентичен в любом случае.
Возвращает
Свойство result ответа содержит id задачи вновь созданной задачи прототипа клавиши. Опросите Получить задачу эндпоинт или подпишитесь на поток до тех пор, пока задача не достигнет SUCCEEDED, затем возьмите запись из candidate_ids и передайте ее вместе с ID задачи в эндпоинт сборки.
Режимы отказа
Name
400 - Bad Request
Description
Запрос был неприемлем. Общие причины:
Отсутствует параметр: image_url обязателен.
Неверный формат изображения: Предоставленный image_url не является поддерживаемым форматом (.jpg, .jpeg, .png, .webp).
Размеры изображения вне диапазона: Изображение слишком маленькое, превышает максимальный размер файла или превышает максимальное количество пикселей.
Недоступный URL: image_url не может быть загружен (404 или timeout).
Неверный Data URI: Строка base64 повреждена.
Контент помечен: Входное изображение было помечено модерацией NSFW.
Name
401 - Unauthorized
Description
Аутентификация не удалась. Пожалуйста, проверьте ваш API-ключ.
Name
402 - Payment Required
Description
Аккаунт находится на бесплатном плане (для создания задач требуется платный план) или недостаточно кредитов.
Name
403 - Forbidden
Description
Входное изображение было помечено модерацией интеллектуальной собственности.
Name
429 - Too Many Requests
Description
Вы превысили ваше ограничение частоты.
Name
500 - Internal Server Error
Description
Произошла неожиданная ошибка на стороне сервера — например, служба модерации контента была недоступна, не удалось подготовить входное изображение или задача не могла быть создана. В этом случае задача не создается, поэтому повторная попытка безопасна.
Запрос
POST
/openapi/creative-lab/keycap/v1/prototype
# Stage 1: generate a finished-keycap design rendercurlhttps://api.meshy.ai/openapi/creative-lab/keycap/v1/prototype \-XPOST \-H"Authorization: Bearer ${YOUR_API_KEY}" \-H'Content-Type: application/json' \-d'{ "image_url": "<your publicly accessible image url or base64-encoded data URI>" }'
Создайте окончательную 3D модель кейкапа с текстурой из успешной прототипной задачи и одного из ее кандидатов. Одна задача сборки запускает весь процесс от начала до конца — генерация белой модели из выбранного дизайна, автоматическая установка и вырезка на основе кейкапа с использованием откалиброванной позы по умолчанию (интерактивная настройка не требуется), полное окрашивание модели и окончательная сборка и экспорт. Сборка обычно занимает 3–7 минут, ближе к верхнему пределу, когда несколько сборок выполняются одновременно. Обратитесь к Объект задачи сборки кейкапа для формы ответа.
Параметры
Name
input_task_id
Type
string
Обязательный
Description
Идентификатор задачи прототипа, созданной через этот же OpenAPI эндпоинт. Прототип должен быть создан тем же аккаунтом Meshy, должен достичь SUCCEEDED и должен произвести хотя бы одного кандидата.
Прототипные задачи, созданные через веб-приложение, не принимаются — эндпоинт сборки принимает только прототипные задачи, произведенные 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.glb и model_urls.obj_zip.
И GLB, и OBJ пакет экспортируются в реальном масштабе миллиметров, с системой координат Y-вверх и передней частью кейкапа, обращенной к +Z.
Режимы отказа
Name
400 - Bad Request
Description
Запрос был неприемлем. Общие причины:
Отсутствует параметр: input_task_id и candidate_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
Указанная прототипная задача не существует, принадлежит другому пользователю или была создана через веб-приложение (только прототипные задачи в режиме API переходят в сборку).
Name
429 - Too Many Requests
Description
Вы превысили ваше ограничение частоты.
Name
500 - Internal Server Error
Description
Произошла неожиданная ошибка на стороне сервера — например, служба модерации контента была недоступна, не удалось подготовить входное изображение или не удалось создать задачу. В этом случае задача не создается, поэтому повторная попытка безопасна.
Запрос
POST
/openapi/creative-lab/keycap/v1/build
# Stage 2: build the chosen candidate into a 3D keycapcurlhttps://api.meshy.ai/openapi/creative-lab/keycap/v1/build \-XPOST \-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 } }'
Получите задачу прототипа или сборки, указав действительный id задачи. Путь URL
должен соответствовать стадии задачи — задача сборки, полученная через
/prototype/:id, вернет 404, и наоборот.
Отменить задачу keycap. Если задача все еще находится в состоянии PENDING, кредиты, использованные при создании, возвращаются. Задачи, которые уже находятся в состоянии IN_PROGRESS, отменяются без возврата (работник может уже использовать ресурсы). Задачи, которые уже достигли конечного состояния (SUCCEEDED, FAILED, CANCELED), не могут быть отменены.
Путь URL должен соответствовать стадии задачи — DELETE на
/prototype/:buildId возвращает 404.
Параметры пути
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
Произошла неожиданная ошибка на стороне сервера при отмене. Задача могла быть или не быть отменена — перечитайте ее, чтобы подтвердить перед повторной попыткой.
Транслируйте обновления в реальном времени для задачи 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. Для задач со статусом PENDING или IN_PROGRESS поток ответа будет включать только необходимые поля progress и status.
Получите список ваших задач keycap с пагинацией для одного этапа. Путь 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: Сортировка по времени создания в порядке убывания.
Объект задачи прототипа клавиши — это рабочая единица, которую Meshy отслеживает для создания одного изображения готового дизайна клавиши из исходной фотографии. Результат этого этапа связывается с этапом сборки через input_task_id плюс candidate_id.
Свойства
Name
id
Type
string
Description
Уникальный идентификатор задачи. Хотя мы используем UUID с k-сортировкой для идентификаторов задач как деталь реализации, вы не должны делать никаких предположений о формате id.
Name
type
Type
string
Description
Тип задачи. Значение — creative-lab-keycap-prototype.
Name
name
Type
string
Description
Имя задачи, указанное при создании задачи. Пустая строка, если имя не было предоставлено.
Name
status
Type
string
Description
Статус задачи. Возможные значения: PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.
Name
progress
Type
integer
Description
Прогресс задачи. Если задача еще не начата, это свойство будет 0. После успешного завершения задачи это значение станет 100.
Name
created_at
Type
timestamp
Description
Временная метка создания задачи в миллисекундах.
Временная метка представляет количество миллисекунд, прошедших с 1 января 1970 года по UTC, согласно стандарту RFC 3339. Например, пятница, 1 сентября 2023 года, 12:00:00 по Гринвичу представляется как 1693569600000. Это применимо ко всем временным меткам в Meshy API.
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
Количество предшествующих задач.
Значение этого поля имеет смысл только если статус задачи PENDING.
Name
task_error
Type
object
Description
Детали ошибки для неудавшихся задач. См. Ошибки для полной справки по объекту task_error.
Name
consumed_credits
Type
integer
Description
Количество кредитов, потребленных этой задачей. Задача, достигшая SUCCEEDED, оплачивается полностью за свой этап. Задача, которая никогда не создается (ошибка 4xx во время запроса, включая отклонение модерации), не оплачивается вообще. Задача, достигшая FAILED, возвращает 0 — плата возвращается, включая асинхронную блокировку модерации. Отмена через DELETE возвращает средства только пока задача еще PENDING; задача, уже находящаяся в IN_PROGRESS, остается оплаченной, так как работа уже выполнена.
Name
image_urls
Type
array of strings
Description
Скачиваемый URL рендера готового дизайна клавиши — как кандидат выглядит как готовая клавиша. Содержит одну запись; image_urls[i] соответствует candidate_ids[i]. Пусто, пока задача не достигнет SUCCEEDED. URL предназначен только для отображения; эндпоинт сборки использует candidate_ids, а не эти URL. Такой же жизненный цикл URL, как у model_urls: подписанный, без заголовка Authorization, действителен до expires_at и стабилен при повторном чтении задачи.
Name
candidate_ids
Type
array of strings
Description
Непрозрачные идентификаторы кандидатов, параллельные image_urls. Передайте запись, соответствующую выбранному вами дизайну, как candidate_id запроса на сборку. Не делайте никаких предположений о формате этих идентификаторов.
Объект задачи сборки Keycap — это рабочая единица, за которой Meshy следит для
создания финальной текстурированной 3D-клавиши из успешной прототипной задачи и
выбранного кандидата. Одна сборка запускает полный конвейер — генерация
белой модели, автоматическая посадка и резка, окраска, сборка и экспорт.
Свойства
Name
id
Type
string
Description
Уникальный идентификатор для задачи.
Name
type
Type
string
Description
Тип задачи. Значение — creative-lab-keycap-build.
Name
name
Type
string
Description
Имя задачи, указанное при создании задачи. Пустая строка, если имя не было предоставлено.
Name
status
Type
string
Description
Статус задачи. Возможные значения: PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.
Name
progress
Type
integer
Description
Прогресс задачи. Если задача еще не начата, это свойство будет 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 во время запроса, включая отклонение модерации), не оплачивается. Задача, достигшая FAILED, возвращает 0 — плата возвращается, включая асинхронную блокировку модерации. Отмена через DELETE возвращает средства только пока задача еще PENDING; задача, уже находящаяся в IN_PROGRESS, остается оплаченной, так как работа уже выполнена.
Name
model_urls
Type
object
Description
Скачиваемые URL для сгенерированных артефактов модели. И GLB, и OBJ пакет экспортируются в реальном масштабе миллиметров, Y-вверх, с передней частью клавиши, обращенной к +Z. Сетки называются keycap-head и keycap-base; когда основа возвращается к заполнению узором, третья сетка keycap-base-interior также присутствует для полости стержня. Не предполагайте наличие ровно двух сеток.
Это подписанные URL: загружайте их без заголовка Authorization. Они остаются действительными до expires_at, что составляет 3 дня после finished_at, и повторное чтение задачи в этом окне возвращает идентичный URL, а не вновь подписанный. Скачайте и сохраните файлы самостоятельно до этого времени — нет возможности обновить истекшую ссылку.
Name
glb
Type
string
Description
Скачиваемый URL к финальной текстурированной model.glb.
Name
obj_zip
Type
string
Description
Скачиваемый URL к zip-пакету, содержащему model.obj, model.mtl и текстурные PNG, на которые ссылается его MTL. Одноцветная основа поставляется только с keycap-head.png; узорчатая основа также поставляется с keycap-base.png.
Name
process_image_urls
Type
object
Description
Скачиваемые URL для промежуточных изображений процесса, ключом является вид. Тот же жизненный цикл URL, что и у model_urls: подписанные, без заголовка Authorization, действительны до expires_at и стабильны при повторном чтении задачи. В настоящее время доступны виды:
head_design — изображение дизайна выбранного кандидата, которое использовалось в сборке (всегда присутствует).
composite — рендер отображения завершенной клавиши выбранного кандидата (присутствует, когда доступно).
base_canvas — окрашенное полотно основы клавиши (присутствует, когда доступно).
Рассматривайте набор ключей как открытый; новые виды могут быть добавлены без нарушения совместимости.
Полный процесс: создать прототип из фотографии, опрашивать его до
SUCCEEDED, выбрать кандидата из candidate_ids, создать сборку с
этим кандидатом, опрашивать сборку до SUCCEEDED, затем скачать GLB и
пакет OBJ из model_urls.
В примере программно выбирается первый кандидат. В реальной
интеграции вы бы отображали запись image_urls конечному пользователю и
позволяли ему выбрать; выбранный индекс отображается 1:1 на candidate_ids.
Полный процесс
POST
/openapi/creative-lab/keycap/v1
#!/usr/bin/env bashset-euopipefail# 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:-}" ]]; thenecho"export IMAGE_PATH (local file) or IMAGE_URL (public url) first">&2exit1fiBASE="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 bodyshift2 out=$(curl--silent--show-error--max-time60--write-out$'\n%{http_code}' \-X"$method""$url"-H"$AUTH""$@") ||return1 http_code=${out##*$'\n'} body=${out%$'\n'*}if ((http_code >=400)); thenecho"HTTP $http_code for $url: $body">&2return1fiprintf'%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:; doif (($(date +%s) >= deadline)); thenecho"gave up waiting for $kind $id">&2return1fi task_status=$(apiGET"$BASE/$kind/$id"|jq-r'.status')echo"$kind: $task_status"case"$task_status"inSUCCEEDED)return0 ;;FAILED|CANCELED)return1 ;;esacsleep"$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"'EXITif [[ -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')"inpng) 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"elseprintf'{"image_url":"%s"}'"$IMAGE_URL">"$BODY"fi# 1. Create the prototype taskPROTO_ID=$(apiPOST"$BASE/prototype" \-H'Content-Type: application/json'--data-binary@"$BODY"|jq-r'.result')# 2. Wait for the design renderpollprototype"$PROTO_ID"# 3. Pick a candidate (first one here; show image_urls to a user in production)CANDIDATE_ID=$(apiGET"$BASE/prototype/$PROTO_ID"|jq-r'.candidate_ids[0]')# 4. Create the build taskjq-n--argp"$PROTO_ID"--argc"$CANDIDATE_ID" \'{input_task_id: $p, candidate_id: $c}'>"$BODY"BUILD_ID=$(apiPOST"$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)pollbuild"$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=$(apiGET"$BASE/build/$BUILD_ID")curl--silent--show-error--fail--max-time900 \-okeycap.glb"$(jq-r '.model_urls.glb' <<<"$TASK")"curl--silent--show-error--fail--max-time900 \-okeycap-obj.zip"$(jq-r '.model_urls.obj_zip' <<<"$TASK")"echo"Done: keycap.glb + keycap-obj.zip"