Перетворіть вихідне фото на багатоколірну піксель-арт фіджет-панель, придатну
для 3D-друку, у два етапи: prototype піксельзує ваше фото на піксель-арт
зображення, а потім build накладає це зображення на сітку 16×16 або 32×32
та перетворює кожен піксель на взаємоблокований квадратний або шестикутний
елемент, який надається у вигляді єдиного файлу 3MF, чиї об'єкти несуть свої
кольори, щоб багатофіламентний слайсер друкував кожен елемент потрібним
кольором. Обидва етапи пов'язані через input_task_id.
POST /openapi/creative-lab/fidget-pixel/v1/prototype
POST /openapi/creative-lab/fidget-pixel/v1/build
Обидва endpoint'и POST вимагають платного плану підписки. Запити з
акаунтів безкоштовного плану відхиляються з кодом 402 Payment Required.
Генерує одне зображення в стилі піксель-арт із вихідного фото. Отриманий ID завдання — це те, що ви передаєте як input_task_id до кінцевої точки build. Викличте цю кінцеву точку ще раз для іншого варіанта, якщо результат вас не влаштовує — кожен виклик тарифікується окремо. Зверніться до
Об'єкт завдання Fidget Pixel Prototype
для опису форми відповіді.
Параметри
Name
image_url
Type
string
Обов'язковий
Description
Вихідне фото, яке Meshy має перетворити на піксель-арт. Наразі підтримуються формати .jpg, .jpeg, .png та .webp.
Формат визначається шляхом декодування даних зображення, а не за розширенням файлу в URL — URL без розширення або той, що перенаправляє, працює, доки байти декодуються у підтримуваний формат. HTTP-перенаправлення відстежуються.
Існує два способи надати зображення:
Публічно доступний URL: URL, доступний з публічного інтернету.
Data URI: закодований у base64 data URI зображення. Приклад data URI: data:image/jpeg;base64,<ваші base64-закодовані дані зображення>.
Name
type
Type
string
Обов'язковий
Description
Що зображено на фото. Визначає стиль пікселізації, тому обирайте свідомо — ці два значення дають помітно різні результати. Доступні значення:
person — суб'єкт є людиною (портрет або на весь зріст). Створює піксельний спрайт суб'єкта у стилі чіબі.
other — усе інше: домашні тварини, об'єкти, маскоти, логотипи, пейзажі. Створює піксельну іконку суб'єкта у стилі бісерного мистецтва.
Name
name
Type
string
Description
Необов'язкова назва завдання для відображення. Максимум 100 символів.
Повертає
Властивість result відповіді містить id завдання щойно створеного прототипу fidget pixel. Опитуйте кінцеву точку Отримати завдання або підпишіться на потік, доки завдання не досягне статусу SUCCEEDED, а потім передайте цей ID до кінцевої точки build як input_task_id.
Режими відмови
Name
400 - Bad Request
Description
Запит неприйнятний. Поширені причини:
Відсутній параметр: image_url та type є обов'язковими.
Недійсний тип: type має бути person або other.
Недійсний формат зображення: наданий 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
Недостатньо кредитів для виконання цього завдання, або API-ключ належить обліковому запису з безкоштовним тарифом.
Name
403 - Forbidden
Description
Вхідне зображення було позначено moderation інтелектуальної власності (Content flagged for intellectual property violation). Блокуються лише облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності; кошти не списуються.
Name
429 - Too Many Requests
Description
Ви перевищили обмеження частоти.
Name
500 - Internal Server Error
Description
Не вдалося завершити саму перевірку інтелектуальної власності (Unable to perform intellectual property check, please try again). Облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності отримують відмову за замовчуванням при збої цієї перевірки; кошти не списуються — повторіть запит.
Request
POST
/openapi/creative-lab/fidget-pixel/v1/prototype
# Stage 1: pixelize the source photocurlhttps://api.meshy.ai/openapi/creative-lab/fidget-pixel/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>", "type": "person" }'
Генерує 3D-друковані деталі з успішно виконаного завдання прототипу. Побудова
накладає піксель-арт зображення прототипу на запитану сітку,
квантує його до щонайбільше color_count кольорів і генерує одну
з'єднувальну деталь на кожну клітинку сітки. Результатом є єдиний файл 3MF, у
якому кожна деталь — це окремий об'єкт із міткою свого кольору, готовий для
мультиматеріального слайсера. Дивіться
Об'єкт завдання побудови Fidget Pixel
для формату відповіді.
Параметри
Name
input_task_id
Type
string
Обов'язковий
Description
ID завдання прототипу, створеного через цю саму кінцеву точку OpenAPI. Прототип має бути створений тим самим обліковим записом Meshy та мати статус SUCCEEDED.
Завдання прототипу, створені через веб-застосунок, не приймаються — кінцева точка build приймає лише завдання прототипу, створені через POST /openapi/creative-lab/fidget-pixel/v1/prototype, і відхиляє будь-яке інше джерело з кодом 404.
Name
name
Type
string
Description
Необов'язкова назва завдання для відображення. Максимум 100 символів.
options
Необов'язкова геометрія деталей. Кожне поле має значення за замовчуванням — надсилайте лише ті, які хочете перевизначити. Це ті самі елементи керування, що доступні у веб-застосунку Creative Lab; висота штифта, масштаб ковпачка та інші виробничі пресети виводяться з shape і piece_size_mm і не доступні окремо.
Name
shape
Type
string
за замовчуванням square
Description
Форма основи кожної деталі. Доступні значення:
square (за замовчуванням) — квадратні деталі на квадратній сітці.
hex — шестикутні деталі на шестикутній сітці. Шестикутні деталі доступні лише в розмірах 6 та 8 мм.
Name
grid_size
Type
integer
за замовчуванням 32
Description
Кількість деталей уздовж кожної сторони плати. Доступні значення: 16 або 32. Сітка 32 зберігає більше деталей; сітка 16 означає менше, але більші деталі для того самого об'єкта.
Name
piece_size_mm
Type
integer
за замовчуванням 8
Description
Довжина ребра кожної деталі в міліметрах. Доступні значення: 6, 8 або 10. Разом з grid_size це визначає розмір надрукованої плати — наприклад 32 × 8 мм ≈ 26 см на сторону. 10 недоступне для shape: "hex" (скошена шестикутна грань утворює навис на більшості споживчих FDM-принтерів).
Name
color_count
Type
integer
за замовчуванням 8
Description
Максимальна кількість кольорів у палітрі, до якої квантується зображення. Діапазон: [1, 8]. Кожен колір стає одним філаментом у вашому слайсері.
Name
piece_height_mm
Type
integer
за замовчуванням 15
Description
Висота кожної деталі в міліметрах. Діапазон: [10, 80].
output
Необов'язковий селектор формату виводу. За замовчуванням 3mf, наразі це єдине підтримуване значення.
Name
format
Type
string
за замовчуванням 3mf
Description
Артефакт, що повертається побудовою. Доступні значення:
3mf (за замовчуванням) — повертає єдиний файл model.3mf за адресою model_urls.3mf, з одним об'єктом на деталь, до якого прикріплено колір деталі.
Повернення
Властивість result відповіді містить id завдання новоствореного завдання побудови fidget pixel. Опитуйте кінцеву точку Отримати завдання або підпишіться на потік, доки завдання не досягне статусу SUCCEEDED, а потім завантажте артефакт із model_urls.3mf.
Режими збою
Name
400 - Bad Request
Description
Запит неприйнятний. Поширені причини:
Відсутній параметр: input_task_id є обов'язковим.
Недійсний UUID: input_task_id не є дійсним UUID.
Батьківське завдання не завершено успішно: Пов'язане завдання прототипу ще не досягло статусу SUCCEEDED.
Немає кандидата: Завдання прототипу завершилося успішно, але не створило піксель-арт зображення; створіть новий прототип.
Параметри поза допустимим діапазоном: Одне з полів options виходить за межі допустимого набору або діапазону — наприклад options.grid_size must be 16 or 32, або options.piece_size_mm=10 is not supported for shape=hex; hex pieces are available in 6 and 8 mm.
Непідтримуваний формат: output.format має бути 3mf.
Name
401 - Unauthorized
Description
Помилка автентифікації. Перевірте свій API-ключ.
Name
402 - Payment Required
Description
Недостатньо кредитів для виконання цього завдання, або API-ключ належить обліковому запису з безкоштовним планом.
Name
403 - Forbidden
Description
Зображення пов'язаного прототипу було позначено moderation інтелектуальної власності. Блокуються лише облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності; кошти не списуються.
Name
404 - Not Found
Description
Пов'язане завдання прототипу не існує, належить іншому користувачу або було створене через веб-застосунок (лише завдання прототипу в режимі API можуть переходити в build).
Name
429 - Too Many Requests
Description
Ви перевищили обмеження частоти.
Name
500 - Internal Server Error
Description
Не вдалося встановити висновок щодо інтелектуальної власності пов'язаного прототипу (Unable to perform intellectual property check, please try again). Облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності при цій перевірці отримують відмову за замовчуванням; кошти не списуються — повторіть запит.
Отримати завдання прототипу або збірки за дійсним id завдання. Шлях URL
має відповідати етапу завдання — якщо завдання збірки отримується через
/prototype/:id, повертається 404, і навпаки.
Унікальний ідентифікатор завдання fidget pixel, яке потрібно отримати.
Повертає
Відповідь містить об'єкт завдання fidget pixel. Форма залежить від того,
який етап було запитано.
Режими збоїв
Name
400 - Bad Request
Description
id не є дійсним UUID (Invalid ID).
Name
403 - Forbidden
Description
Зображення завдання було позначене модерацією інтелектуальної власності. Блокуються лише облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності.
Name
404 - Not Found
Description
Завдання не існує, належить іншому користувачеві, або його етап не відповідає шляху URL.
Name
500 - Internal Server Error
Description
Не вдалося завершити перевірку інтелектуальної власності (Unable to perform intellectual property check, please try again); облікові записи Enterprise з увімкненою фільтрацією інтелектуальної власності блокують запит у разі помилки. Повторіть запит.
Скасувати завдання fidget pixel. Якщо завдання ще перебуває у стані PENDING, кредити,
витрачені під час створення, повертаються. Завдання, що вже перебувають у стані
IN_PROGRESS, скасовуються без повернення коштів (воркер, можливо, уже
витрачає ресурси). Завдання, що вже досягли кінцевого стану
(SUCCEEDED, FAILED, CANCELED), скасувати неможливо.
Шлях URL повинен відповідати стадії завдання — DELETE за адресою
/prototype/:buildId повертає 404.
Параметри шляху
Name
id
Type
path
Description
Унікальний ідентифікатор завдання fidget pixel, яке потрібно скасувати.
Повертає
У разі успіху повертає 204 No Content з порожнім тілом.
Режими збоїв
Name
400 - Bad Request
Description
Запит було неприйнятно. Поширені причини:
Недійсний ID: id не є дійсним UUID.
Кінцевий стан: Завдання вже перебуває у стані SUCCEEDED, FAILED або CANCELED і не може бути скасоване.
Name
404 - Not Found
Description
Завдання не існує, належить іншому користувачу, або його стадія не відповідає шляху URL.
Отримуйте оновлення в реальному часі для задачі fidget pixel через Server-Sent Events (SSE).
Шлях URL має відповідати етапу задачі — відкриття потоку за адресою
/prototype/:buildId/stream видає одне корисне навантаження event: error зі
значенням status_code: 404 і закриває потік; некоректний id призводить до того самого з
status_code: 400 (Invalid ID).
Параметри
Name
id
Type
path
Description
Унікальний ідентифікатор задачі fidget pixel, для якої потрібно отримати потік.
Повертає
Повертає потік об'єктів задачі Fidget Pixel Prototype
або Fidget Pixel Build у форматі
Server-Sent Events. Кожен кадр містить повний об'єкт задачі для відповідного етапу — таку саму структуру,
яку повертає кінцева точка Get, — тому поки задача має статус PENDING або IN_PROGRESS,
вихідні поля просто ще не заповнені (null, [] або {}), а
finished_at дорівнює null.
Отримайте пагінований список ваших завдань fidget pixel для одного етапу.
Шлях 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: Сортування за часом створення у порядку спадання.
Об'єкт задачі прототипу Fidget Pixel — це одиниця роботи, яку Meshy відстежує
для перетворення вихідного фото на зображення у стилі пікс-арт. Результат цього
етапу передається на етап побудови
через input_task_id.
Властивості
Name
id
Type
string
Description
Унікальний ідентифікатор задачі. Хоча як деталь реалізації ми використовуємо k-сортований UUID для ідентифікаторів задач, вам не слід робити жодних припущень щодо формату id.
Name
type
Type
string
Description
Тип задачі. Значення — creative-lab-fidget-pixel-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
Мітка часу початку виконання задачі, у мілісекундах. Якщо задача ще не розпочата, це значення — null.
Name
finished_at
Type
timestamp
Description
Мітка часу завершення задачі, у мілісекундах. Якщо задача ще не завершена, це значення — null.
Name
expires_at
Type
timestamp
Description
Мітка часу закінчення терміну дії результату задачі, у мілісекундах — через 3 дні після завершення задачі. Для корпоративних облікових записів результати API зберігаються безстроково (див. Зберігання ресурсів); для них ця мітка часу встановлюється приблизно на 100 років уперед.
Name
preceding_tasks
Type
integer
Description
Кількість задач, що передують цій.
Значення цього поля має сенс лише якщо статус задачі — PENDING.
Name
task_error
Type
object
Description
Деталі помилки для невдалих задач. Повний опис об'єкта task_error дивіться у розділі Помилки.
Name
consumed_credits
Type
integer
Description
Кількість кредитів, витрачених цією задачею. Задача, яка досягає статусу SUCCEEDED, стягується у повному обсязі за свій етап. Задача, яка так і не була створена (4xx під час запиту, включно з відхиленням через moderation), не стягується взагалі. Задача, яка досягає статусу FAILED, повертає 0 — стягнута сума повертається. Скасування через DELETE повертає кошти лише поки задача ще має статус PENDING; задача, що вже перебуває у статусі IN_PROGRESS, залишається оплаченою, оскільки робота вже виконана.
Name
image_urls
Type
array of strings
Description
Посилання для завантаження зображення у стилі пікс-арт, згенерованого цією задачею прототипу. Наразі API завжди повертає рівно одне зображення; поле є масивом, щоб майбутні версії могли надавати декілька варіантів без порушення сумісності. Порожнє, доки задача не досягне статусу SUCCEEDED.
Це підписані URL-адреси: отримуйте їх без заголовка Authorization. Вони залишаються дійсними до expires_at, тобто протягом 3 днів після finished_at, і повторне зчитування задачі в цей період повертає ту саму URL-адресу, а не нову підписану. Завантажте та збережіть файли самостійно до цього моменту — відновити прострочене посилання неможливо.
Об'єкт Fidget Pixel Build Task — це робоча одиниця, яку Meshy відстежує для
генерації придатних для друку деталей з успішно виконаного завдання-прототипу. Побудова
семплує піксель-арт зображення прототипу на запитувану сітку та публікує
єдиний 3MF-файл з кольоровими тегами.
Властивості
Name
id
Type
string
Description
Унікальний ідентифікатор завдання.
Name
type
Type
string
Description
Тип завдання. Значення — creative-lab-fidget-pixel-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
Мітка часу початку виконання завдання, у мілісекундах. null до моменту запуску завдання.
Name
finished_at
Type
timestamp
Description
Мітка часу завершення завдання, у мілісекундах. null до моменту завершення завдання.
Name
expires_at
Type
timestamp
Description
Мітка часу, коли закінчується термін дії результату завдання, у мілісекундах — 3 дні після завершення завдання. Корпоративні акаунти зберігають результати API безстроково (див. Зберігання ресурсів); для них ця мітка часу встановлюється приблизно на 100 років вперед.
Name
preceding_tasks
Type
integer
Description
Кількість завдань у черзі перед цим. Має значення лише коли статус — PENDING.
Name
task_error
Type
object
Description
Деталі помилки для завдань, що завершилися невдало. Див. Помилки для повного опису об'єкта task_error.
Name
consumed_credits
Type
integer
Description
Кількість кредитів, витрачених на це завдання. За завдання, що досягло статусу SUCCEEDED, стягується повна сума за його етап. За завдання, яке так і не було створено (4xx під час запиту, включно з відхиленням через moderation), плата не стягується взагалі. Завдання, що досягло статусу FAILED, повертає 0 — кошти повертаються. Скасування через DELETE повертає кошти лише поки завдання ще має статус PENDING; за завдання, що вже перебуває в статусі IN_PROGRESS, плата залишається стягнутою, оскільки робота вже виконана.
Name
model_urls
Type
object
Description
URL-адреси для завантаження згенерованого ресурсу, з ключами за форматом. Містить рівно один запис — формат, запитаний через параметр output.format у запиті на побудову. Порожнє, доки завдання не досягне статусу SUCCEEDED.
Це підписані URL-адреси: отримуйте їх без заголовка Authorization. Вони залишаються дійсними до моменту expires_at, тобто 3 дні після finished_at, і повторне зчитування завдання в межах цього періоду повертає ідентичну URL-адресу, а не нову підписану. Завантажте та збережіть файли самостійно до цього моменту — способу оновити прострочене посилання не існує.
Name
3mf
Type
string
Description
URL-адреса для завантаження файлу 3MF. Один об'єкт на кожну деталь, кожен позначений своїм кольором з палітри, тому багатофіламентний слайсер призначає філаменти за кольором. Присутнє, коли output.format мав значення 3mf (типове значення).
Повний потік: створити прототип із фотографії, опитувати його до
SUCCEEDED, створити на його основі build, опитувати build до SUCCEEDED, а потім
завантажити 3MF з model_urls.
Прототип зазвичай завершується протягом кількох хвилин; build зазвичай
завершується значно швидше, ніж за хвилину. У реальній інтеграції ви б показали
елемент image_urls прототипу кінцевому користувачу і дали б йому підтвердити
(або повторно запустити прототип), перш ніж витрачати кредити на build.
Complete flow
POST
/openapi/creative-lab/fidget-pixel/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://...# export PIXEL_TYPE=person # or: other:"${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">&2exit1fiPIXEL_TYPE=${PIXEL_TYPE:-person}BASE="https://api.meshy.ai/openapi/creative-lab/fidget-pixel/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'{"type":"%s","image_url":"data:%s;base64,'"$PIXEL_TYPE""$MIME"base64<"$IMAGE_PATH"|tr-d'\n'printf'"}' } >"$BODY"elsejq-n--argt"$PIXEL_TYPE"--argu"$IMAGE_URL" \'{type: $t, image_url: $u}'>"$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 pixel-art image (show image_urls[0] to a user in production)pollprototype"$PROTO_ID"# 3. Create the build task (defaults: square pieces, 32x32 grid, 8 mm, 8 colors, 15 mm tall)jq-n--argp"$PROTO_ID" \'{input_task_id: $p, options: {shape: "square", grid_size: 32, piece_size_mm: 8, color_count: 8, piece_height_mm: 15}, output: {format: "3mf"}}'>"$BODY"BUILD_ID=$(apiPOST"$BASE/build" \-H'Content-Type: application/json'--data-binary@"$BODY"|jq-r'.result')# 4. Wait for the piecespollbuild"$BUILD_ID"# 5. Download the 3MF. This is a signed URL: no Authorization header,# and it stays valid for 3 days after the task finishes.TASK=$(apiGET"$BASE/build/$BUILD_ID")curl--silent--show-error--fail--max-time900 \-ofidget-pixel.3mf"$(jq-r '.model_urls["3mf"]' <<<"$TASK")"echo"Done: fidget-pixel.3mf"