Creative Lab — Keycap API

Перетворіть вихідну фотографію на повнокольоровий кастомний ковпачок клавіші механічної клавіатури у два етапи: prototype генерує рендер дизайну "готового ковпачка" з вашого вхідного фото. Після того, як ви підтвердили цей рендер, build перетворює його на текстуровану 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 разом з ID завдання прототипу до endpoint для build. Дивіться Об'єкт завдання прототипу кейкапа щодо структури відповіді.

Параметри

  • 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,<ваші base64-закодовані дані зображення>.
  • Name
    name
    Type
    string
    Description

    Необов'язкова назва завдання для відображення. Максимум 100 символів.

  • Name
    remove_background
    Type
    boolean
    за замовчуванням false
    Description

    Якщо встановлено значення true, відображуваний рендер, повернутий у image_urls, є прозорим RGBA PNG з видаленим фоном, щоб ви могли накласти його на будь-який фон.

    Це стосується лише відображуваного рендера. Кандидат, який використовує endpoint для build, залишається незмінним, тому 3D-результат буде однаковим в обох випадках.

Повертає

Властивість result відповіді містить id завдання новоствореного прототипу кейкапа. Опитуйте endpoint Отримати завдання або підпишіться на потік, доки завдання не досягне статусу SUCCEEDED, після чого візьміть елемент з candidate_ids і передайте його разом з ID завдання до endpoint для build.

Режими збою

  • 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

    Обліковий запис перебуває на безкоштовному тарифі (для створення завдань потрібен платний тариф) або має недостатньо кредитів.

  • Name
    403 - Forbidden
    Description

    Вхідне зображення було позначено системою moderation інтелектуальної власності.

  • Name
    429 - Too Many Requests
    Description

    Ви перевищили своє обмеження частоти.

  • Name
    500 - Internal Server Error
    Description

    Сталася неочікувана помилка на стороні сервера — наприклад, сервіс модерації контенту був недоступний, не вдалося виконати проміжне збереження вхідного зображення, або не вдалося створити завдання. У цьому випадку завдання не створюється, тому повторити спробу безпечно.

Request

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

Response

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

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

Створення завдання на побудову ковпачка клавіші (Keycap)

Згенеруйте фінальну текстуровану 3D-модель ковпачка клавіші з успішного завдання-прототипу та одного з його кандидатів. Одне завдання на побудову виконує весь конвеєр від початку до кінця — генерацію білої моделі з обраного дизайну, автоматичне позиціонування та обрізання на основі ковпачка з використанням каліброваної позиції за замовчуванням (без потреби в інтерактивному налаштуванні), розфарбовування повної моделі, а також фінальне складання та експорт. Побудова зазвичай триває 3–7 хвилин, ближче до верхньої межі, коли одночасно виконується кілька побудов. Зверніться до розділу Об'єкт завдання на побудову Keycap для опису форми відповіді.

Параметри

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

    Ідентифікатор завдання-прототипу, створеного через цю саму кінцеву точку OpenAPI. Прототип має бути створений тим самим обліковим записом Meshy, повинен досягти статусу SUCCEEDED і має мати щонайменше одного кандидата.

    Завдання-прототипи, створені через веб-застосунок, не приймаються — кінцева точка build приймає лише завдання-прототипи, створені через 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 profile 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 вийшло за межі дозволеного діапазону або набору значень enum.
  • 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

    Сталася неочікувана помилка на боці сервера — наприклад, служба модерації контенту була недоступна, не вдалося підготувати вхідне зображення, або завдання не вдалося створити. У цьому випадку завдання не створюється, тому повторити спробу безпечно.

Request

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

Response

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

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

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

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

Форми відповіді дивіться в The Keycap Prototype Task Object та The Keycap Build Task Object.

Параметри

  • Name
    id
    Type
    path
    Description

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

Повертає

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

Request

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

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=***"
  }
}

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

Delete a Keycap Task

Скасувати завдання 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

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

Request

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

Response

// 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. Кожен кадр містить повний об'єкт завдання для відповідного етапу — та сама форма, яку повертає кінцева точка Get — тому поки завдання перебуває у стані PENDING або IN_PROGRESS, вихідні поля просто ще не заповнені (null, [] або {}), а finished_at дорівнює null.

Request

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.
// 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=***"
  }
}

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

List Keycap Tasks

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

Повертає

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

Request

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

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

Об'єкт завдання прототипу ковпачка клавіші

Об'єкт Keycap Prototype Task — це одиниця роботи, яку 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

    Progress завдання. Якщо завдання ще не почалося, ця властивість матиме значення 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 під час запиту, включно з відхиленням через moderation), не оплачується взагалі. Завдання, що досягає статусу FAILED, повертає 0 — оплата повертається, включно з випадком асинхронного блокування через moderation. Скасування через 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"
  ]
}

Об'єкт задачі побудови Keycap

Об'єкт задачі побудови Keycap — це робоча одиниця, яку Meshy відстежує для генерації фінальної текстурованої 3D-клавіші (keycap) з успішно виконаної прототипної задачі та обраного кандидата. Одна побудова виконує повний конвеєр — генерацію білої моделі, автоматичне посадження та обрізку, розфарбовування, збірку та експорт.

Властивості

  • 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-up, при цьому передня частина клавіші звернена до +Z. Сітки (meshes) названі keycap-head та keycap-base; коли основа переходить до заповнення за шаблоном (pattern fill), також присутня третя сітка keycap-base-interior для порожнини під стрижень. Не припускайте, що завжди буде рівно дві сітки.

    Це підписані URL-адреси: отримуйте їх без заголовка Authorization. Вони залишаються дійсними до expires_at, що становить 3 дні після finished_at, і повторне читання задачі протягом цього періоду повертає ідентичний URL, а не заново підписаний. Завантажте та збережіть файли самостійно до цього моменту — способу оновити застарілу URL-адресу не існує.

    • Name
      glb
      Type
      string
      Description

      URL-адреса для завантаження фінального текстурованого файлу model.glb.

    • Name
      obj_zip
      Type
      string
      Description

      URL-адреса для завантаження zip-пакету, що містить model.obj, model.mtl та PNG-текстури, на які фактично посилається його MTL. Однотонна (solid-color) основа постачається лише з keycap-head.png; основа з візерунком (patterned) також постачається з keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    URL-адреси для завантаження проміжних зображень процесу, згруповані за типом. Той самий життєвий цикл URL, що й у model_urls: підписані, без заголовка Authorization, дійсні до expires_at, і стабільні при повторному читанні задачі. Наразі формуються такі типи:

    • head_design — зображення дизайну обраного кандидата, яке було використано побудовою (завжди присутнє).
    • composite — фінальне відображення готової клавіші (keycap) для обраного кандидата (присутнє, коли доступне).
    • 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.

Complete flow

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"