Přeměňte zdrojovou fotografii na plnobarevný vlastní mechanický klávesový kryt ve dvou fázích: prototyp generuje vykreslení návrhu "hotového klávesového krytu" z vaší vstupní fotografie. Jakmile potvrdíte toto vykreslení, sestavení jej přemění na 3D model klávesového krytu s texturou v jednom běhu — generování bílého modelu, automatické usazení a oříznutí na kalibrované výchozí pozici, plnobarevné modelování a finální montáž probíhají všechny v rámci jednoho úkolu sestavení. Obě fáze jsou propojeny prostřednictvím input_task_id plus candidate_id.
POST /openapi/creative-lab/keycap/v1/prototype
POST /openapi/creative-lab/keycap/v1/build
Oba POST endpointy vyžadují placený plán předplatného. Požadavky z účtů s bezplatným plánem jsou odmítnuty s 402 Payment Required.
Vygenerujte render designu hotové klávesy ze zdrojové fotografie. Výsledek úkolu obsahuje pole image_urls (zobrazení renderu hotové klávesy) a paralelní pole candidate_ids; obě obsahují jeden záznam. Zavolejte tento koncový bod znovu pro další render, pokud výsledek není podle vašich představ — každý hovor je účtován zvlášť. Předejte candidate_id spolu s ID úkolu prototypu na koncový bod sestavení. Podívejte se na
Objekt úkolu prototypu klávesy
pro tvar odpovědi.
Parametry
Name
image_url
Type
string
Povinné
Description
Zdrojová fotografie pro Meshy k přeměně na obrázky designu klávesy. V současné době podporujeme formáty .jpg, .jpeg, .png a .webp.
Formát je detekován dekódováním dat obrázku, ne z přípony souboru URL — URL bez přípony nebo taková, která přesměrovává, funguje, pokud bajty dekódují na podporovaný formát. HTTP přesměrování jsou sledována. EXIF orientace je normalizována, takže otočená fotografie z telefonu je použita tak, jak vypadá.
Limity: alespoň 32 pixelů na každé straně, maximálně 178,956,970 pixelů celkem a maximálně 20,000,000 bajtů po stažení. Pro data URI se limit vztahuje na dekódované bajty, takže samotný zdrojový soubor může být až do této velikosti — je to base64 text, který je asi o třetinu větší, což je důležité pro vaše tělo požadavku, ne pro tento limit. Data URI musí deklarovat obsahový typ image/* a ;base64.
Existují dva způsoby, jak poskytnout obrázek:
Veřejně přístupná URL: URL, která je přístupná z veřejného internetu.
Data URI: Base64-kódovaná data URI obrázku. Příklad data URI: data:image/jpeg;base64,<vaše base64-kódovaná data obrázku>.
Name
name
Type
string
Description
Volitelný název úkolu pro účely zobrazení. Maximálně 100 znaků.
Name
remove_background
Type
boolean
výchozí false
Description
Pokud je nastaveno na true, zobrazený render vrácený v image_urls je průhledný RGBA PNG s odstraněným pozadím, takže jej můžete složit na jakékoli pozadí.
To platí pouze pro zobrazený render. Kandidát, který koncový bod sestavení spotřebovává, není ovlivněn, takže 3D výsledek je stejný v obou případech.
Vrací
Vlastnost result odpovědi obsahuje ID úkolu nově vytvořeného úkolu prototypu klávesy. Dotazujte Získat úkol koncový bod nebo se přihlaste k odběru streamu, dokud úkol nedosáhne SUCCEEDED, poté vezměte záznam z candidate_ids a předejte jej spolu s ID úkolu na koncový bod sestavení.
Rozměry obrázku mimo rozsah: Obrázek je příliš malý, překračuje maximální velikost souboru nebo překračuje maximální počet pixelů.
Nedostupná URL: image_url nemohla být stažena (404 nebo timeout).
Neplatná Data URI: Base64 řetězec je poškozený.
Obsah označen: Vstupní obrázek byl označen NSFW moderací.
Name
401 - Unauthorized
Description
Autentizace selhala. Zkontrolujte prosím svůj API klíč.
Name
402 - Payment Required
Description
Účet je na bezplatném plánu (pro vytvoření úkolů je vyžadován placený plán) nebo nemá dostatečné kredity.
Name
403 - Forbidden
Description
Vstupní obrázek byl označen moderací duševního vlastnictví.
Name
429 - Too Many Requests
Description
Překročili jste svůj limit rychlosti.
Name
500 - Internal Server Error
Description
Došlo k neočekávané chybě na straně serveru — například služba moderace obsahu nebyla dostupná, staging vstupního obrázku selhal nebo úkol nemohl být vytvořen. V tomto případě není vytvořen žádný úkol, takže opakování je bezpečné.
Požadavek
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>" }'
Generování finálního 3D modelu klávesy s texturou z úspěšného prototypového úkolu a jednoho z jeho kandidátů. Jeden úkol pro sestavení spouští celý proces od začátku do konce — generování bílého modelu z vybraného návrhu, automatické usazení a ořezání na základnu klávesy pomocí kalibrované výchozí pozice (není potřeba interaktivní úprava), barvení celého modelu a finální montáž a export. Sestavení obvykle trvá 3–7 minut, blíže k horní hranici, když běží několik sestavení současně. Viz Objekt úkolu pro sestavení klávesy pro tvar odpovědi.
Parametry
Name
input_task_id
Type
string
Povinné
Description
ID úkolu prototypu vytvořeného prostřednictvím tohoto stejného OpenAPI koncového bodu. Prototyp musí být vytvořen stejným účtem Meshy, musí dosáhnout SUCCEEDED a musí produkovat alespoň jednoho kandidáta.
Prototypové úkoly vytvořené prostřednictvím webové aplikace nejsou přijímány — koncový bod pro sestavení přijímá pouze prototypové úkoly produkované POST /openapi/creative-lab/keycap/v1/prototype a odmítá jakýkoli jiný zdroj s 404.
Name
candidate_id
Type
string
Povinné
Description
Kandidát k sestavení, vybraný z pole candidate_ids úspěšného prototypového úkolu. Musí patřit k tomuto úkolu; jakákoli jiná hodnota je odmítnuta s 400.
Name
name
Type
string
Description
Volitelný název úkolu pro zobrazení. Maximálně 100 znaků.
options
Volitelné ladění geometrie. Každé pole má kalibrovanou výchozí hodnotu — posílejte pouze ty, které chcete přepsat.
Name
base_model
Type
string
výchozí cherry-mx-1x1-r1
Description
Základna klávesy, na které se bude stavět. Aktuálně je jedinou dostupnou hodnotou cherry-mx-1x1-r1 — standardní klávesa Cherry MX profilu 1u. Plánuje se 3–5 dalších hlavních standardních velikostí; vlastní velikosti nejsou podporovány.
Name
head_size_mm
Type
number
výchozí 23
Description
Cílová velikost sochařské hlavy v milimetrech: její nejdelší rozměr je škálován na tuto hodnotu. Rozsah: [10, 40]. Hodnoty nad přibližně 32.9 mohou být zmenšeny, aby hlava stále zapadala do ochranného limitu základny, takže dodaný nejdelší rozměr může být menší než požadovaný. Aplikovaná hodnota dnes není zpětně odražena v objektu úkolu — pokud potřebujete potvrdit velikost, kterou jste skutečně obdrželi, změřte ohraničující kvádr sítě keycap-head ve staženém modelu.
Name
vertical_offset_mm
Type
number
výchozí 0
Description
Vertikální posun aplikovaný na hlavu před jejím usazením na základnu, v milimetrech. Rozsah: [-5, 5].
Návraty
Vlastnost result odpovědi obsahuje id nově vytvořeného úkolu pro sestavení klávesy. Dotazujte koncový bod Získat úkol nebo se přihlaste k odběru streamu, dokud úkol nedosáhne SUCCEEDED, poté stáhněte artefakty z model_urls.glb a model_urls.obj_zip.
Jak GLB, tak OBJ balíček jsou exportovány v skutečné světové měřítku v milimetrech, s Y-nahoru souřadnicovým systémem a přední částí klávesy směřující +Z.
Režimy selhání
Name
400 - Bad Request
Description
Požadavek byl nepřijatelný. Běžné příčiny:
Chybějící parametr: input_task_id a candidate_id jsou povinné.
Neplatný UUID: input_task_id není platný UUID.
Rodič nedosáhl úspěchu: Odkazovaný prototypový úkol ještě nedosáhl SUCCEEDED.
Žádní kandidáti: Prototypový úkol uspěl, ale neprodukoval žádné kandidáty.
Neznámý kandidát: candidate_id není jedním z kandidátů vstupního úkolu.
Možnosti mimo rozsah: Jedno z polí options spadlo mimo povolený rozsah nebo množinu hodnot.
Name
401 - Unauthorized
Description
Autentizace selhala. Zkontrolujte prosím svůj API klíč.
Name
402 - Payment Required
Description
Účet je na bezplatném plánu (pro vytvoření úkolů je vyžadován placený plán) nebo má nedostatečné kredity.
Name
404 - Not Found
Description
Odkazovaný prototypový úkol neexistuje, patří jinému uživateli nebo byl vytvořen prostřednictvím webové aplikace (pouze prototypové úkoly v režimu API se řetězí do sestavení).
Name
429 - Too Many Requests
Description
Překročili jste svůj limit rychlosti.
Name
500 - Internal Server Error
Description
Došlo k neočekávané chybě na straně serveru — například služba pro moderování obsahu nebyla dostupná, staging vstupního obrázku selhal nebo úkol nemohl být vytvořen. V tomto případě není vytvořen žádný úkol, takže opakování je bezpečné.
Požadavek
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 } }'
Načtěte úkol prototypu nebo sestavení pomocí platného id úkolu. Cesta URL
musí odpovídat fázi úkolu — úkol sestavení načtený přes
/prototype/:id vrátí 404, a naopak.
Zrušení úkolu keycap. Pokud je úkol stále PENDING, kredity
spotřebované při vytvoření jsou vráceny. Úkoly, které jsou již
IN_PROGRESS, jsou zrušeny bez náhrady (pracovník již může
spotřebovávat zdroje). Úkoly, které již dosáhly konečného stavu
(SUCCEEDED, FAILED, CANCELED), nelze zrušit.
Cesta URL musí odpovídat fázi úkolu — DELETE na
/prototype/:buildId vrací 404.
Parametry cesty
Name
id
Type
path
Description
Unikátní identifikátor pro úkol keycap, který má být zrušen.
Vrací
Vrací 204 No Content při úspěchu s prázdným tělem.
Režimy selhání
Name
400 - Bad Request
Description
Úkol je již v konečném stavu a nelze jej zrušit.
Name
404 - Not Found
Description
Úkol neexistuje, patří jinému uživateli nebo jeho fáze neodpovídá cestě URL.
Name
500 - Internal Server Error
Description
Došlo k neočekávané chybě na straně serveru při rušení. Úkol mohl, ale nemusel být zrušen — před opakováním jej znovu přečtěte pro potvrzení.
Streamujte aktualizace v reálném čase pro úkol keycap prostřednictvím Server-Sent Events (SSE).
Cesta URL musí odpovídat fázi úkolu — otevření streamu na
/prototype/:buildId/stream vydá jediný event: error payload s
status_code: 404 a uzavře stream.
Parametry
Name
id
Type
path
Description
Unikátní identifikátor pro úkol keycap ke streamování.
Návratové hodnoty
Vrací stream objektů úkolu Keycap Prototype
nebo Keycap Build jako
Server-Sent Events. Pro úkoly PENDING nebo IN_PROGRESS bude stream
odpovědi obsahovat pouze potřebná pole progress a status.
Získejte stránkovaný seznam vašich úkolů keycap pro jednu fázi. Cesta URL
vybírá fázi — /prototype vrací úkoly prototypu; /build
vrací úkoly sestavení. Úkoly z jiné fáze nejsou zahrnuty v žádné z odpovědí.
Parametry cesty
Name
stage
Type
path
Povinné
Description
Buď prototype nebo build. Kolekce vrací pouze úkoly,
jejichž fáze odpovídá URL — načítání /prototype nikdy nevrací
úkoly sestavení a naopak.
Parametry dotazu
Name
page_num
Type
integer
výchozí 1
Description
Číslo stránky pro stránkování.
Name
page_size
Type
integer
výchozí 10
Description
Limit velikosti stránky. Maximální povolené je 100 položek.
Name
sort_by
Type
string
výchozí -created_at
Description
Pole pro třídění. Dostupné hodnoty:
+created_at: Třídit podle času vytvoření vzestupně.
-created_at: Třídit podle času vytvoření sestupně.
Objekt úkolu prototypu klávesy je pracovní jednotka, kterou Meshy sleduje, aby vygenerovala jeden obrázek dokončeného návrhu klávesy z výchozí fotografie. Výstup této fáze je propojen do fáze sestavení prostřednictvím input_task_id plus candidate_id.
Vlastnosti
Name
id
Type
string
Description
Unikátní identifikátor pro úkol. I když používáme k-tříděné UUID pro id úkolů jako implementační detail, neměli byste dělat žádné předpoklady o formátu id.
Name
type
Type
string
Description
Typ úkolu. Hodnota je creative-lab-keycap-prototype.
Name
name
Type
string
Description
Název úkolu zadaný při vytvoření úkolu. Prázdný řetězec, pokud nebyl poskytnut žádný název.
Name
status
Type
string
Description
Stav úkolu. Možné hodnoty jsou PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.
Name
progress
Type
integer
Description
Pokrok úkolu. Pokud úkol ještě nezačal, tato vlastnost bude 0. Jakmile úkol uspěje, stane se 100.
Name
created_at
Type
timestamp
Description
Časové razítko, kdy byl úkol vytvořen, v milisekundách.
Časové razítko představuje počet milisekund uplynulých od 1. ledna 1970 UTC, podle
standardu RFC 3339.
Například pátek, 1. září 2023 12:00:00 PM GMT je reprezentován jako 1693569600000. To platí
pro všechna časová razítka v Meshy API.
Name
started_at
Type
timestamp
Description
Časové razítko, kdy byl úkol zahájen, v milisekundách. Pokud úkol ještě nezačal, tato vlastnost bude 0.
Name
finished_at
Type
timestamp
Description
Časové razítko, kdy byl úkol dokončen, v milisekundách. Pokud úkol ještě není dokončen, tato vlastnost bude 0.
Name
expires_at
Type
timestamp
Description
Časové razítko, kdy výsledek úkolu vyprší, v milisekundách.
Name
preceding_tasks
Type
integer
Description
Počet předcházejících úkolů.
Hodnota tohoto pole má smysl pouze pokud je stav úkolu PENDING.
Name
task_error
Type
object
Description
Podrobnosti o chybě pro neúspěšné úkoly. Viz Chyby pro úplnou referenci objektu task_error.
Name
consumed_credits
Type
integer
Description
Počet kreditů spotřebovaných tímto úkolem. Úkol, který dosáhne SUCCEEDED, je účtován plnou částkou za svou fázi. Úkol, který nikdy není vytvořen (chyba 4xx v době žádosti, včetně odmítnutí moderace) není účtován vůbec. Úkol, který dosáhne FAILED, vrací 0 — poplatek je vrácen, včetně asynchronního blokování moderace. Zrušení prostřednictvím DELETE vrací peníze pouze pokud je úkol stále PENDING; úkol, který je již IN_PROGRESS, zůstává účtován, protože práce byla vynaložena.
Name
image_urls
Type
array of strings
Description
Stahovatelná URL vykreslení dokončeného návrhu klávesy — jak kandidát vypadá jako dokončená klávesa. Obsahuje jeden záznam; image_urls[i] odpovídá candidate_ids[i]. Prázdné, dokud úkol nedosáhne SUCCEEDED. URL je pouze pro zobrazení; koncový bod sestavení spotřebovává candidate_ids, ne tyto URL. Stejný životní cyklus URL jako model_urls: podepsané, bez hlavičky Authorization, platné do expires_at a stabilní, když je úkol znovu přečten.
Name
candidate_ids
Type
array of strings
Description
Neprůhledné identifikátory kandidátů, paralelní k image_urls. Předávejte záznam odpovídající vašemu vybranému návrhu jako candidate_id v žádosti o sestavení. Nedělejte žádné předpoklady o formátu těchto id.
Objekt úkolu Keycap Build je pracovní jednotka, kterou Meshy sleduje pro
generování finální texturované 3D klávesy z úspěšného prototypového úkolu a
vybraného kandidáta. Jediný build spouští celý pipeline — generování bílého
modelu, automatické usazení a řezání, barvení, montáž a export.
Vlastnosti
Name
id
Type
string
Description
Unikátní identifikátor pro úkol.
Name
type
Type
string
Description
Typ úkolu. Hodnota je creative-lab-keycap-build.
Name
name
Type
string
Description
Název úkolu zadaný při vytvoření úkolu. Prázdný řetězec, pokud nebyl zadán žádný název.
Name
status
Type
string
Description
Stav úkolu. Možné hodnoty jsou PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.
Name
progress
Type
integer
Description
Postup úkolu. Pokud úkol ještě nezačal, tato vlastnost bude 0. Jakmile úkol uspěje, stane se 100.
Name
created_at
Type
timestamp
Description
Časové razítko, kdy byl úkol vytvořen, v milisekundách.
Name
started_at
Type
timestamp
Description
Časové razítko, kdy byl úkol zahájen, v milisekundách.
Name
finished_at
Type
timestamp
Description
Časové razítko, kdy byl úkol dokončen, v milisekundách.
Name
expires_at
Type
timestamp
Description
Časové razítko, kdy výsledek úkolu vyprší, v milisekundách.
Name
preceding_tasks
Type
integer
Description
Počet předcházejících úkolů. Má smysl pouze, když je stav PENDING.
Name
task_error
Type
object
Description
Podrobnosti o chybách pro neúspěšné úkoly. Viz Chyby pro úplný odkaz na objekt task_error.
Name
consumed_credits
Type
integer
Description
Počet kreditů spotřebovaných tímto úkolem. Úkol, který dosáhne SUCCEEDED, je účtován plnou částkou za svou fázi. Úkol, který nikdy nevznikne (chyba 4xx v době požadavku, včetně odmítnutí moderace), není účtován vůbec. Úkol, který dosáhne FAILED, vrátí 0 — poplatek je vrácen, včetně asynchronního bloku moderace. Zrušení pomocí DELETE vrací peníze pouze tehdy, když je úkol stále PENDING; úkol, který je již IN_PROGRESS, zůstává účtován, protože práce byla vynaložena.
Name
model_urls
Type
object
Description
Stahovatelné URL pro generované modelové artefakty. Oba balíčky GLB a OBJ jsou exportovány v reálném měřítku v milimetrech, Y-up, s přední stranou klávesy směřující +Z. Sítě jsou pojmenovány keycap-head a keycap-base; když základna přejde na vzorovou výplň, je také přítomna třetí síť keycap-base-interior pro dutinu stonku. Nepředpokládejte přesně dvě sítě.
Jedná se o podepsané URL: stáhněte je bez hlavičky Authorization. Zůstávají platné do expires_at, což je 3 dny po finished_at, a opětovné čtení úkolu v tomto okně vrátí identické URL místo nově podepsaného. Stáhněte a uložte soubory sami předtím — není možné obnovit vypršený odkaz.
Name
glb
Type
string
Description
Stahovatelná URL na finální texturovaný model.glb.
Name
obj_zip
Type
string
Description
Stahovatelná URL na zip balíček obsahující model.obj, model.mtl a texturové PNG, které jeho MTL skutečně odkazuje. Základna s jednobarevným povrchem obsahuje pouze keycap-head.png; vzorovaná základna také obsahuje keycap-base.png.
Name
process_image_urls
Type
object
Description
Stahovatelné URL pro mezilehlé procesní obrázky, klíčované podle druhu. Stejný životní cyklus URL jako model_urls: podepsané, bez hlavičky Authorization, platné do expires_at, a stabilní při opětovném čtení úkolu. Aktuálně emitované druhy:
Kompletní tok: vytvořte prototyp z fotografie, dotazujte ho na
SUCCEEDED, vyberte kandidáta z candidate_ids, vytvořte sestavení s
tímto kandidátem, dotazujte sestavení na SUCCEEDED, poté stáhněte GLB a
balíček OBJ z model_urls.
Příklad programově vybírá prvního kandidáta. V reálné integraci byste
zobrazili položku image_urls koncovému uživateli a nechali ho vybrat;
vybraný index mapuje 1:1 na candidate_ids.
Kompletní tok
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"