Creative Lab — Keycap API

Перетворіть вихідне фото на повнокольорову кастомну клавішу механічної клавіатури в два етапи: прототип генерує рендер дизайну "готової клавіші" з вашого вхідного фото. Після підтвердження цього рендера, збірка перетворює його на текстуровану 3D модель клавіші в одному запуску — генерація білої моделі, автоматичне розміщення та різання на каліброваній стандартній позі, повне фарбування моделі та остаточна збірка відбуваються в межах одного завдання збірки. Два етапи пов'язані через input_task_id плюс candidate_id.

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

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

Створення завдання прототипу клавіші

Генеруйте рендер дизайну готової клавіші з вихідного фото. Результат завдання містить масив image_urls (рендер дисплея готової клавіші) і паралельний масив candidate_ids; обидва містять один запис. Викличте цю кінцеву точку знову для іншого рендера, якщо результат не відповідає вашим очікуванням — кожен виклик оплачується окремо. Передайте candidate_id разом з ідентифікатором завдання прототипу до кінцевої точки збірки. Зверніться до Об'єкт завдання прототипу клавіші для форми відповіді.

Параметри

  • Name
    image_url
    Type
    string
    Обов'язковий
    Description

    Вихідне фото для Meshy, щоб перетворити його на зображення дизайну клавіші. Наразі ми підтримуємо формати .jpg, .jpeg, .png та .webp.

    Формат визначається шляхом декодування даних зображення, а не з розширення файлу 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 і передайте його разом з ідентифікатором завдання до кінцевої точки збірки.

Режими відмови

  • 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 key.

  • 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 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>"
  }'

Відповідь

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

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

Створення завдання на побудову кейкапа

Генерація фінальної текстурованої 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.

Режими відмови

  • 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 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
    }
  }'

Відповідь

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

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

Отримання Завдання Keycap

Отримайте прототип або завдання на створення, вказавши дійсний id завдання. Шлях URL має відповідати стадії завдання — запит завдання на створення через /prototype/:id поверне 404, і навпаки.

Зверніться до Об'єкт Завдання Прототипу Keycap та Об'єкт Завдання на Створення Keycap для формату відповідей.

Параметри

  • Name
    id
    Type
    path
    Description

    Унікальний ідентифікатор завдання keycap для отримання.

Повертає

Відповідь містить об'єкт завдання keycap. Формат залежить від запитаної стадії.

Запит

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

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

Відповідь Прототипу

{
  "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"
  ]
}

Відповідь Створення

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

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

Видалення завдання Keycap

Скасувати завдання keycap. Якщо завдання ще PENDING, кредити, використані під час створення, повертаються. Завдання, які вже IN_PROGRESS, скасовуються без повернення (працівник може вже використовувати ресурси). Завдання, які вже досягли кінцевого стану (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

    Виникла несподівана помилка на сервері під час скасування. Завдання могло бути скасоване або ні — перечитайте його, щоб підтвердити перед повторною спробою.

Запит

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

Відповідь

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

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

Транслювати Завдання Keycap

Транслюйте оновлення в реальному часі для завдання 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.

Запит

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

Response Stream

// Error event example (wrong stage or task not found)
event: error
data: {
  "status_code": 404,
  "message": "Task not found"
}

// Message event examples illustrate task progress.
// For PENDING or IN_PROGRESS tasks, the response stream will not include all fields.
event: message
data: {
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "progress": 0,
  "status": "PENDING"
}

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

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

Перелік завдань Keycap

Отримайте пагінований список ваших завдань 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: Сортувати за часом створення у спадаючому порядку.

Повертає

Повертає пагінований список об'єктів завдань за етапами — або об'єкт завдання прототипу keycap при переліку /prototype, або об'єкт завдання збірки keycap при переліку /build.

Запит

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

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

Відповідь (Перелік завдань прототипу)

[
  {
    "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"
    ]
  }
]

Об'єкт Завдання Прототипу Клавіші

Об'єкт Завдання Прототипу Клавіші — це робоча одиниця, яку Meshy відстежує для генерації одного зображення готового дизайну клавіші з вихідного фото. Вихід цього етапу зв'язується з етапом створення через input_task_id плюс candidate_id.

Властивості

  • Name
    id
    Type
    string
    Description

    Унікальний ідентифікатор для завдання. Хоча ми використовуємо k-сортований UUID для ідентифікаторів завдань як деталь реалізації, ви не повинні робити жодних припущень щодо формату 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

    Мітка часу створення завдання, у мілісекундах.

  • Name
    started_at
    Type
    timestamp
    Description

    Мітка часу початку завдання, у мілісекундах. Якщо завдання ще не розпочато, ця властивість буде 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Мітка часу завершення завдання, у мілісекундах. Якщо завдання ще не завершено, ця властивість буде 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Мітка часу, коли результат завдання закінчується, у мілісекундах.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Кількість попередніх завдань.

  • Name
    task_error
    Type
    object
    Description

    Деталі помилки для невдалих завдань. Дивіться Помилки для повної довідки по об'єкту task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Кількість кредитів, спожитих цим завданням. Завдання, яке досягає SUCCEEDED, стягує повну суму за свій етап. Завдання, яке ніколи не створюється (помилка 4xx під час запиту, включаючи відхилення модерації), не стягується взагалі. Завдання, яке досягає 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 запиту на створення. Не робіть жодних припущень щодо формату цих ідентифікаторів.

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"
  ]
}

Об'єкт Завдання Побудови Клавіші

Об'єкт Завдання Побудови Клавіші — це робоча одиниця, за якою 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 — полотно пофарбованої основи клавіші (присутнє, коли доступне).

    Розглядайте набір ключів як відкритий; нові типи можуть бути додані без порушення сумісності.

Example Keycap Build Task Object

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

Приклад від початку до кінця

Повний процес: створити прототип з фото, перевірити його до SUCCEEDED, вибрати кандидата з candidate_ids, створити збірку з цим кандидатом, перевірити збірку до SUCCEEDED, потім завантажити GLB та пакет OBJ з model_urls.

Приклад програмно вибирає першого кандидата. У реальній інтеграції ви б відобразили запис image_urls кінцевому користувачу і дозволили б йому вибрати; обраний індекс відображається 1:1 на candidate_ids.

Повний процес

POST
/openapi/creative-lab/keycap/v1
#!/usr/bin/env bash
set -euo pipefail

# Requires curl and jq. Point IMAGE_PATH at a local photo, or IMAGE_URL at a public one:
#   export MESHY_API_KEY=msy_...
#   export IMAGE_PATH=./portrait.jpg          # or: export IMAGE_URL=https://...
: "${MESHY_API_KEY:?export MESHY_API_KEY first}"
if [[ -z "${IMAGE_PATH:-}" && -z "${IMAGE_URL:-}" ]]; then
  echo "export IMAGE_PATH (local file) or IMAGE_URL (public url) first" >&2
  exit 1
fi

BASE="https://api.meshy.ai/openapi/creative-lab/keycap/v1"
AUTH="Authorization: Bearer $MESHY_API_KEY"

# api METHOD URL [curl args...] -> prints the response body, non-zero on failure.
# Note we do not use -f/--fail: it discards the body, and the body is the only
# place the reason appears.
api() {
  local method=$1 url=$2 out http_code body
  shift 2
  out=$(curl --silent --show-error --max-time 60 --write-out $'\n%{http_code}' \
    -X "$method" "$url" -H "$AUTH" "$@") || return 1
  http_code=${out##*$'\n'}
  body=${out%$'\n'*}
  if ((http_code >= 400)); then
    echo "HTTP $http_code for $url: $body" >&2
    return 1
  fi
  printf '%s' "$body"
}

# Each task gets its own 40-minute budget.
poll() {
  local kind=$1 id=$2 delay=5 task_status deadline
  deadline=$(($(date +%s) + 2400))
  while :; do
    if (($(date +%s) >= deadline)); then
      echo "gave up waiting for $kind $id" >&2
      return 1
    fi
    task_status=$(api GET "$BASE/$kind/$id" | jq -r '.status')
    echo "$kind: $task_status"
    case "$task_status" in
    SUCCEEDED) return 0 ;;
    FAILED | CANCELED) return 1 ;;
    esac
    sleep "$delay"
    delay=$((delay * 2 > 30 ? 30 : delay * 2))
  done
}

# Build the request body in a file. A base64 data URI must never go on the
# command line or into an exported variable - a photo of any real size will
# exceed the OS argument limit.
BODY=$(mktemp)
trap 'rm -f "$BODY"' EXIT
if [[ -n "${IMAGE_PATH:-}" ]]; then
  # Declare the real type: the API accepts JPEG, PNG and WebP.
  case "$(printf '%s' "${IMAGE_PATH##*.}" | tr 'A-Z' 'a-z')" in
    png) MIME=image/png ;;
    webp) MIME=image/webp ;;
    *) MIME=image/jpeg ;;
  esac
  {
    printf '{"image_url":"data:%s;base64,' "$MIME"
    base64 <"$IMAGE_PATH" | tr -d '\n'
    printf '"}'
  } >"$BODY"
else
  printf '{"image_url":"%s"}' "$IMAGE_URL" >"$BODY"
fi

# 1. Create the prototype task
PROTO_ID=$(api POST "$BASE/prototype" \
  -H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')

# 2. Wait for the design render
poll prototype "$PROTO_ID"

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

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

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

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